【问题标题】:What does send() do in Ruby?send() 在 Ruby 中做了什么?
【发布时间】:2010-07-26 17:22:41
【问题描述】:

谁能告诉我什么

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

是吗?

【问题讨论】:

  • 这是整行代码吗?我的意思是,在“发送”之前什么都没有?

标签: ruby


【解决方案1】:

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

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

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

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


如果send前真的没有变量,说明使用的是全局Object:

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

【讨论】:

  • 哦,我明白了,所以如果想在数据库中存储类似 1.month 的内容,而不是静态地说出天数,可以使用 send。
  • 没错,您可以使用它来调用具有计算名称而不是静态名称的方法。 (但是,您不应该允许不受限制的用户输入,以避免调用私有方法......但是,您可以给它们一个唯一的前缀:send 'user_method_'+methodname, *args)
  • 好的用例可能是你想测试一个受保护的类方法,你可以在一个类之外调用它——在测试文件中..
【解决方案2】:

send 是一个 ruby​​(没有 rails)方法,允许通过名称调用另一个方法。

来自文档

   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】:

我认为 .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

【讨论】:

  • 感谢伟大的链接
  • 以这种方式使用 .send 会增加不必要的复杂性,并且更容易无意中将错误引入代码。例如,在上面的代码中,如果您向参数哈希添加新条目(例如“圆柱体”),代码将失败并出现未定义的方法错误。
  • respond_to?如果需要,可用于防止此类错误。
  • 这是一个很好的解释!谢谢贾!
  • @Kevin 你是对的,但有时它可能是必要的。更大的灵活性与更多的风险相关,可以减轻风险。
【解决方案4】:

另一个例子,类似于 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

【讨论】:

  • 感谢简单易懂的解释!
  • 谢谢!这正是我所追求的答案。想知道这个常用吗?我在遗留代码中遇到了类似的东西,不确定我应该坚持下去。@Mike Vallano
  • @b-liu 我已经看到有经验的开发人员在新代码中使用它。使用define_methodapidock.com/ruby/Module/define_method时也很有帮助。
  • 太棒了!多谢! @MikeVallano
【解决方案5】:

发送有什么作用?

send 是“调用方法”的另一种方式。示例:

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

Send lives in the Object class.

这样做有什么好处?

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

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

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

【讨论】:

    【解决方案6】:

    Send 也可以用来展示 Ruby 中的一切都是一个对象

    1.send(:+, 1)  ## -> 2
    3.send(:*, 2)  ## -> 6
    

    【讨论】:

      【解决方案7】:

      视图的另一个用例:

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

      允许。您可以编写可处理各种对象的可扩展视图 与:

          render 'your_view_path', object: "my_object"
      

      【讨论】:

      • 这会为视图添加不必要的逻辑,并且可能会产生安全隐患。不要这样做。使用数组和哈希。
      猜你喜欢
      • 2011-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-20
      • 2013-10-08
      • 2011-01-24
      • 1970-01-01
      相关资源
      最近更新 更多