send()在Ruby中做什么?


96

有人可以告诉我什么吗

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

是,现在呢?


2
这是整个代码行吗?我的意思是,“发送”之前没有任何内容吗?
giraff

Answers:


107

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

实际上,这些行是等效的:

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

请注意,它send绕过了可见性检查,因此您也可以调用私有方法(对于单元测试很有用)。


如果在发送之前确实没有任何变量,则意味着使用了全局对象:

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

1
哦,我明白了,如果有人想在数据库中存储1.month之类的东西,而不是静态地说出天数,那么可以使用send。
Christian Bankester 2010年

3
是的,您可以使用它来调用具有经过计算的名称(而不是静态名称)的方法。(不过,为避免调用私有方法,您不应允许无限制的用户输入。但是,您可以给它们提供一个唯一的前缀:send'user_method _'+ methodname,* args)
giraff 2010年

2
用好情况下可能是它,你想测试一个受保护类的方法,你可以外面称之为类的测试文件..
GN。


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会增加不必要的复杂性,并且更容易在无意间将错误引入代码中。例如,在上面的代码中,如果将新条目添加到参数哈希(例如“ cylinders”),则代码将失败,并出现未定义的方法错误。
Kevin Schwerdtfeger 2015年

1
回应?如果需要,可用于防止此类错误。
Richard_G 2015年

1
这是很好的解释!谢谢哈!
Sharath'8

1
@Kevin,您是对的,但有时可能有必要。更大的灵活性与更大的风险相关联,可以降低风险。
谢泼德

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

谢谢!这正是我所追求的答案。想知道这是常用的吗?我在旧版代码中遇到了类似的情况,不确定是否应该坚持使用。@ Mike Vallano
B Liu

1
@ b-liu我已经在经验丰富的开发人员的新代码中看到了它。在使用define_method以下命令时也可能会有所帮助:apidock.com/ruby/Module/define_method
迈克·瓦拉诺

太棒了!谢谢堆!@MikeVallano
乙柳

4

发送做什么?

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

最好通过示例说明:

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

在Object类中发送生命

这样做有什么好处?

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

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

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


0

视图的另一个用例:

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

允许。您将编写可伸缩视图,该视图可与以下各种对象一起使用:

    render 'your_view_path', object: "my_object"

这会给视图增加不必要的逻辑,并可能带来安全隐患。不要这样 使用数组和哈希。
Derrek Bertrand
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.