2010-07-26 35 views

回答

65

send将消息发送到一个对象实例和其在类层次结构的祖先直到一些方法进行反应(因为它的名字的第一个参数相匹配)。

实事求是地讲,这些线路是等价的:

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

注意send绕过可视性检查,这样就可以调用私有方法,太(单元测试非常有用)。


如果真的发送之前没有变化,这意味着全球的对象用于:

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

哦,我明白了,所以如果有人想在数据库中存储诸如1.month之类的东西,而不是静态地说出天数,可以使用send。 – 2010-07-26 20:00:04

+2

确实,您可以使用它来调用计算名称的方法,而不是静态的。 (尽管如此,你不应该允许无限制的用户输入,以避免调用私有方法......但是,你可以给它们一个唯一的前缀:send'user_method _'+ methodname,* args) – giraff 2010-07-26 20:06:40

+0

好的用例可能是你想要的要测试受保护的类方法,您可以将它称为类入内测试文件.. – 2017-06-28 02:40:26

69

send是一个ruby(无导轨)方法,允许通过名称调用另一个方法。

从技术文档

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

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

+3

很好的答案,比详细的接受答案更清晰。 – 2015-06-16 21:53:37

33

一个最有用的功能,我认为与方法。发送的是,它可以动态调用on方法。这可以为您节省很多打字。 .send方法最流行的用法之一是动态分配属性。例如:

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

定期属性分配一个需要

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

或者使用方法。发送:

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 
+0

感谢您的好链接 – 2015-07-07 12:10:10

+3

以这种方式使用.send会增加不必要的复杂性,并且可以更轻松地在代码中无意中引入错误。例如,在上面的代码中,如果向参数散列添加一个新条目(例如'cylinders'),代码将会失败并显示未定义的方法错误。 – 2015-08-05 12:06:24

+1

respond_to?可以用来防止这种错误,如果需要的话。 – 2015-10-04 19:14:51

8

另一个例子,类似安东尼桑杰·贾的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 
+0

感谢您的简单和简单的解释! – 2017-09-17 16:30:09

+0

谢谢!这正是我所追求的答案。想知道这是常用的吗?我在遗留代码中遇到了类似的东西,我不确定我应该坚持下去。@ Mike Vallano – 2017-10-23 03:51:01

+0

@ b-liu我见过它被有经验的开发人员用于新代码中。当使用'define_method'时,它也会很有帮助:https://apidock.com/ruby/Module/define_method。 – 2017-11-02 11:18:01

0

另一个用例的观点:

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

允许。你写可伸缩视图谁与所有种类的对象 与:

render 'your_view_path', object: "my_object"