2

ActiveRecord::Baseの動作と同様に機能する関数を作成しようとしていますfind_by_'column_name'。たとえば、次のようなことをすると

User.find_by_address("1234 Apple Road")

列を介して検索されaddressます。しかし、私はそれがどのように機能するかについて困惑しています。

コード内の「動的マッチャー」のコード (例:ここself.prefix) を見ると、 と の両方が表示されますが、私の調査では、Ruby についてもRuby についても何も見つかりません。self.suffixself.prefixself.suffix

この種の関数を作成するにはどうすればよいですか?

4

2 に答える 2

5

これはmethod_missing、認識できない名前のメソッドが呼び出されたときに Ruby が提供するコールバックです。これは、Ruby で動的な名前を持つメソッドを作成する標準的な方法です。

渡された最初の引数は、メソッドの名前を表す Symbol であり、認識されないメソッドに渡されたすべての引数を受け取ります。

于 2013-07-09T20:49:48.260 に答える
1

あなたが動物園を持っているとしましょう。たくさんの野生動物がいるとても素敵な動物園です。もちろん、動物園の飼育係として、ニーズや特性に基づいて特定の動物を見つける必要があることがよくあります。しかし、動物園がどんどん大きくなるにつれて、これらの特徴がどうなるかを前もって知ることは不可能です! これを修正してみましょう...

まず、動物とは何かを定義しましょう。

class Animal
  def initialize(attributes)
    @attributes = attributes
  end

  def [](value)
    @attributes[value]
  end
end

簡単です。さぁ、動物園を作ろう!

class Zoo
  def animals
    @animals ||= []
  end
end

動物がいない動物園とは?

zoo = Zoo.new

zoo.animals << Animal.new(type: "Mighty Giraffe", legs: 4, region: 'Africa')
zoo.animals << Animal.new(type: "Fierce Pidgin", legs: 2, region: 'America')
zoo.animals << Animal.new(type: "Wild Boar", legs: 4, region: 'Africa')

完全。私たちは今、動物でいっぱいの動物園を持っています。今では、それぞれに特徴があることはわかっていますが、まだ見つけることができていません.

zoo.find_animals_by_region('Africa')

しかし、覚えておいてください、私たちはこれらすべての特徴を前もって知りません! 動物園に特別なメソッドを追加して、これを修正してみましょう。

class Zoo
  def animals
    @@animals ||= []
  end

  def method_missing(method_name, *args, &block)
    # stuff here
  end
end

これで、Zoo の未定義メソッドへのすべての呼び出しをキャッチできるようになりました。つまり、find_animals_by_something は未定義であるため、すぐにキャッチされます。さらに、使用された method_name も取得します。すごい!これを有効に活用しましょう。

class Zoo
  def animals
    @@animals ||= []
  end

  def method_missing(method_name, *args, &block)
    if method_name.to_s.start_with?('find_animals_by_')
      # here we go!
    end
  end
end

どうぞ!特別なキーワード「find_animals_by_」で始まる欠落しているメソッドのみをキャッチするようになりました。そこに少しロジックを追加して、不要なメソッドに対して super を呼び出すことを忘れないでください!

class Zoo
  def animals
    @@animals ||= []
  end

  def method_missing(method_name, *args, &block)
    if method_name.to_s.start_with?('find_animals_by_')
      find_animals_by_attribute(method_name[16..-1], args[0])
    else
      super(method_name, *args, &block)
    end
  end

  def find_animals_by_attribute(attribute, value)
    animals.select{ |animal| animal[attribute.to_sym] == value }
  end
end

終わり!動物を検索できる完全に機能する動物園!

于 2013-07-09T23:27:33.050 に答える