2

はじめに: Rails 3.2; 'a' はオブジェクトであり、ActiveRecord モデルであり、これは has_many メッセージ (ActiveRecord モデルでもあります) ですが、それはおそらく私の質問にとってはあまり重要ではありません。

ここで質問です。なぜこれが、

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

しかし、これもまた、

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

?

何が起こっていますか?明らかに、ここにはいくつかの Ruby マジックがあり、オブジェクトを探索するこれらの方法で異なる結果が得られます。1つはArrayクラスを照会していると思いますが、もう1つは照会しています... :where (他のメソッドの中でも)に応答するものです。それを何と呼ぶべきかさえ知りません。私の推測では、それは Array クラスのオブジェクトにいくつかのものを照会していると思います...「混合」?(Ruby のコンテキストで使用される用語をよく耳にしたと思います...)

4

1 に答える 1

1

ここの犯人はありそうmethod_missingです。

Ruby と Rails の「魔法のような」側面の多くは、この気の利いた小さなメソッドによるものです。基本的に、NoMethodError をスローする前の最後の努力として、Ruby はmethod_missingそのオブジェクトで呼び出されたメソッドを呼び出します。これにより、Rails (4.0 より前) が のような動的ファインダーに応答できるようになりfind_by_name_and_emailます。すべてのモデルで考えられるすべての列の組み合わせを定義するのはばかげているため、Railsmethod_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 に答える