루비에서 send ()는 무엇을합니까?


96

누군가 나에게 무엇을 말해 줄 수 있습니까?

send("#{Model.find...}")

이고 무엇입니까?


2
이것이 전체 코드 라인입니까? '보내기'전에는 아무것도 없나요?
giraff 2010-07-26

답변:


107

send 일부 메서드가 반응 할 때까지 (이름이 첫 번째 인수와 일치하기 때문에) 클래스 계층 구조의 개체 인스턴스와 조상에게 메시지를 보냅니다.

실질적으로이 라인은 동일합니다.

1.send '+', 2
1.+(2)
1 + 2

send가시성 검사 를 우회하므로 개인 메서드도 호출 할 수 있습니다 (단위 테스트에 유용함).


보내기 전에 실제로 변수가 없으면 전역 개체가 사용됨을 의미합니다.

send :to_s    # "main"
send :class   # Object

1
오, 그렇군요. 정적으로 일 수를 말하는 대신 데이터베이스에 1.month와 같은 것을 저장하려면 send를 사용할 수 있습니다.
Christian Bankester

3
사실, 정적이 아닌 계산 된 이름으로 메서드를 호출하는 데 사용할 수 있습니다. (단, 비공개 메서드 호출을 피하기 위해 무제한 사용자 입력을 허용해서는 안됩니다 ... 그러나 고유 한 접두사를 지정할 수 있습니다. send 'user_method _'+ methodname, * args)
giraff

2
좋은 사용 사례는 보호 된 클래스 메서드를 테스트하려는 경우 일 수 있습니다
.


63

.send 메소드로 생각하는 가장 유용한 기능 중 하나는 동적으로 메소드를 호출 할 수 있다는 것입니다. 이것은 많은 타이핑을 절약 할 수 있습니다. .send 메서드의 가장 널리 사용되는 용도 중 하나는 속성을 동적으로 할당하는 것입니다. 예를 들면 :

class Car
  attr_accessor :make, :model, :year
end  

정기적으로 속성을 할당하려면

c = Car.new
c.make="Honda"
c.model="CRV"
c.year="2014"

또는 .send 방법 사용 :

c.send("make=", "Honda")
c.send("model=", "CRV")
c.send("year=","2014")

그러나 모두 다음으로 대체 할 수 있습니다.

Rails 앱이 사용자 입력에서 자동차 클래스에 속성을 할당해야한다고 가정하면 다음을 수행 할 수 있습니다.

c = Car.new()
params.each do |key, value|
  c.send("#{key}=", value)
end

위대한 링크에 대한 감사
sid_09

7
이러한 방식으로 .send를 사용하면 불필요한 복잡성이 추가되고 실수로 코드에 버그를 쉽게 추가 할 수 있습니다. 예를 들어, 위 코드에서 매개 변수 해시에 새 항목 (예 : '실린더')을 추가하면 정의되지 않은 메서드 오류와 함께 코드가 실패합니다.
Kevin Schwerdtfeger 2015-08-05

1
응답? 원하는 경우 이러한 오류를 방지하는 데 사용할 수 있습니다.
Richard_G 2015 년

1
이것은 훌륭한 설명이었습니다! 감사합니다 Jha!
Sharath

1
@Kevin 당신이 옳지 만 때로는 필요할 수 있습니다. 더 많은 유연성은 더 많은 위험과 관련되어 완화 될 수 있습니다.
Will Sheppard

12

Antonio Jha의 https://stackoverflow.com/a/26193804/1897857 과 유사한 또 다른 예

객체에 대한 속성을 읽어야하는 경우입니다.

예를 들어 문자열 배열이있는 경우 문자열을 반복하고 개체에서 호출하면 작동하지 않습니다.

atts = ['name', 'description']
@project = Project.first
atts.each do |a|
  puts @project.a
end
# => NoMethodError: undefined method `a'

그러나 다음과 send같이 객체에 문자열을 지정할 수 있습니다 .

atts = ['name', 'description']
@project = Project.first
atts.each do |a|
  puts @project.send(a)
end
# => Vandalay Project
# => A very important project

간단하고 쉬운 설명 감사합니다!
Junan Chakma

감사! 그것이 바로 제가 추구하는 대답입니다. 이것이 일반적으로 사용되는지 궁금하십니까? 내가 레거시 코드에서 비슷한 건너 온, 모르겠 나는 그것으로 충실해야 @ 마이크 Vallano.
B 리우

1
@ b-liu 경험 많은 개발자들이 새로운 코드에서 사용하는 것을 보았습니다. 사용하는 경우 그것은 또한 도움이 될 수 있습니다 define_method: apidock.com/ruby/Module/define_method .
Mike Vallano 2017

대박! 감사합니다! @MikeVallano
B 류

4

보내기는 무엇을합니까?

send 메서드를 호출하는 또 다른 방법입니다.

이것은 예를 통해 가장 잘 설명됩니다.

o = Object.new
o.send(:to_s) # => "#<Object:0x00005614d7a24fa3>"
# is equivalent to:
o.to_s # => "#<Object:0x00005614d7a24fa3>"

Object 클래스에서 생명을 보냅니다 .

ths의 이점은 무엇입니까?

이 접근 방식의 이점은 호출하려는 메서드를 매개 변수로 전달할 수 있다는 것입니다. 다음은 간단한 예입니다.

def dynamically_call_a_method(name)
    o = Object.new
    o.send name 
end
dynamically_call_a_method(:to_s) # => "#<Object:0x00005614d7a24fa3>"

호출하려는 메서드를 전달할 수 있습니다. 이 경우 우리는 :to_s. 이것은 루비 메타 프로그래밍을 할 때 매우 편리 할 수 ​​있습니다. 이것은 우리가 다른 요구 사항에 따라 다른 메서드를 호출 할 수있게 해주기 때문입니다.


0

뷰의 또 다른 사용 사례 :

    <%= link_to 
    send("first_part_of_path_#{some_dynamic_parameters}_end_path", 
    attr1, attr2), ....
    %>

허용하다 . 다음을 사용하여 모든 종류의 객체로 작업하는 확장 가능한 뷰를 작성합니다.

    render 'your_view_path', object: "my_object"

이것은 뷰에 불필요한 논리를 추가하고 보안에 영향을 미칠 수 있습니다. 이러지마 배열과 해시를 사용하십시오.
Derrek Bertrand
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.