send()在Ruby中做了什么?

Chr*_*ter 88 ruby

有人可以告诉我什么

send("#{Model.find...}")
Run Code Online (Sandbox Code Playgroud)

是吗?

Nik*_*bak 97

send是一个ruby(没有rails)方法,允许按名称调用另一个方法.

从文档

   class Klass
     def hello(*args)
       "Hello " + args.join(' ')
     end
   end
   k = Klass.new
   k.send :hello, "gentle", "readers"   #=> "Hello gentle readers"
Run Code Online (Sandbox Code Playgroud)

http://corelib.rubyonrails.org/classes/Object.html#M001077

  • 很好的答案,比详细接受的答案更清晰. (5认同)

gir*_*aff 96

send 在类层次结构中向对象实例及其祖先发送消息,直到某些方法作出反应(因为其名称与第一个参数匹配).

实际上,这些线是等价的:

1.send '+', 2
1.+(2)
1 + 2
Run Code Online (Sandbox Code Playgroud)

请注意,send绕过可见性检查,以便您也可以调用私有方法(对单元测试很有用).


如果在发送之前确实没有变量,则表示使用了全局Object:

send :to_s    # "main"
send :class   # Object
Run Code Online (Sandbox Code Playgroud)

  • 没错,您可以使用它来调用计算名称而不是静态名称的方法.(但是,您不应该允许不受限制的用户输入,以避免调用私有方法...但是,您可以为它们提供唯一的前缀:send'user_method _'+ methodname,*args) (3认同)
  • 好的用例可能是您想要测试受保护的类方法,您可以在类之外调用它 - 在测试文件中.. (2认同)

小智 54

我认为.send方法最有用的功能之一是它可以动态调用方法.这可以为您节省大量的打字.最常用的.send方法之一是动态分配属性.例如:

class Car
  attr_accessor :make, :model, :year
end  
Run Code Online (Sandbox Code Playgroud)

要定期分配属性,需要

c = Car.new
c.make="Honda"
c.model="CRV"
c.year="2014"
Run Code Online (Sandbox Code Playgroud)

或者使用.send方法:

c.send("make=", "Honda")
c.send("model=", "CRV")
c.send("year=","2014")
Run Code Online (Sandbox Code Playgroud)

但它可以全部替换为以下内容:

假设您的Rails应用程序需要从用户输入为您的汽车类分配属性,您可以这样做

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

  • 以这种方式使用.send会增加不必要的复杂性,并且更容易无意中将错误引入代码中.例如,在上面的代码中,如果向参数哈希添加新条目(例如"柱面"),则代码将因未定义的方法错误而失败. (7认同)
  • 回应?如果需要,可用于防止此类错误。 (2认同)

Mik*_*ano 8

另一个例子,类似于Antonio Jha的/sf/answers/1833566311/

是你需要读取对象的属性.

例如,如果您有一个字符串数组,如果您尝试迭代它们并在对象上调用它们,它将无法工作.

atts = ['name', 'description']
@project = Project.first
atts.each do |a|
  puts @project.a
end
# => NoMethodError: undefined method `a'
Run Code Online (Sandbox Code Playgroud)

但是,您可以send将字符串添加到对象:

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


BKS*_*eon 6

发送有什么作用?

send 是调用方法的另一种方式。

这最好通过示例来说明:

o = Object.new
o.send(:to_s) # => "#<Object:0x00005614d7a24fa3>"
# is equivalent to:
o.to_s # => "#<Object:0x00005614d7a24fa3>"
Run Code Online (Sandbox Code Playgroud)

发送生活在 Object 类中

这样做有什么好处?

这种方法的好处是你可以将你想要调用的方法作为参数传入。这是一个简单的例子:

def dynamically_call_a_method(method_name)
    o = Object.new
    o.send method_name
end
dynamically_call_a_method(:to_s) # => "#<Object:0x00005614d7a24fa3>"
Run Code Online (Sandbox Code Playgroud)

你可以传入你想要调用的方法。在这种情况下,我们传入了:to_s. 这在进行 ruby​​ 元编程时非常方便,因为这允许我们根据不同的需求调用不同的方法。


小智 5

Send 还可以用来展示 Ruby 中的所有内容都是对象

1.send(:+, 1)  ## -> 2
3.send(:*, 2)  ## -> 6
Run Code Online (Sandbox Code Playgroud)