2

简介:Rails 3.2;'a' 是一个对象和 ActiveRecord 模型,它有_many 消息(也是 ActiveRecord 模型)——尽管这对我的问题可能不是很重要。

那么问题来了:为什么会这样,

  • irb(main):046:0> a.messages.respond_to?(:where) => true

但还有这个,

  • irb(main):047:0> a.messages.methods.include?(:where) => false

?

发生了什么?显然,这里有一些 Ruby 魔法,这使得这些探索对象的方式产生了不同的结果;我猜一个是查询 Array 类,另一个是查询...响应 :where的东西(以及其他方法)。也不知道该叫什么。我的猜测是它正在用一些东西查询 Array 类的对象......“混合”?(我想我在 Ruby 上下文中经常听到这个词......)

4

1 回答 1

1

这里的罪魁祸首很可能method_missing

Ruby 和 Rails 的许多“神奇”方面都归功于这个漂亮的小方法。基本上,作为抛出 NoMethodError 之前的最后努力,Ruby 调用了一个method_missing对其对象调用的方法。这允许 Rails(4.0 之前)响应动态查找器,例如find_by_name_and_email. 在所有模型中定义所有可能的列组合是很可笑的,因此 Rails 重载method_missing并在那里构造相关的 SQL 查询。

此外,当您要使用 响应方法调用method_missing时,您可以覆盖 Ruby 的respond_to?方法。

这是一个例子:

class Foo
  def method_missing(meth, *args, &block)
    if meth == :bar
      puts 'yep!'
    else
      super
    end
  end

  def respond_to?(meth)
    if meth == :bar
      true
    else
      super
    end
  end
end

foo = Foo.new
foo.methods.include?(:bar)
# => false
foo.respond_to?(:bar)
# => true
于 2013-08-18T23:17:56.670 回答