Ruby でメソッドが呼び出された時にレシーバがあるかないかで処理を切り分ける
今日の Kaigi on Rails の kamipo さんの基調講演でそういう話がでてたのでやってみました。
要は User.where
みたいに User.
付きか where
だけで呼び出された場合で処理を切り分けたい的な話。
class User def self.where "レシーバなし" end def self.where_with_receiver "レシーバあり" end class <<self private :where # private メソッドでレシーバありで呼び出された場合に method_missing が呼ばれる def method_missing(name, *args) if name === :where where_with_receiver(*args) else super end end end end pp User.where # => レシーバあり pp User.instance_exec { where } # => レシーバなし # 動的呼び出しの場合 pp User.send(:where) # => レシーバなし pp User.public_send(:where) # => レシーバあり # NOTE: self. 付きは Ruby のバージョンによって変わる pp User.instance_exec { self.where } # Ruby 2.6 以前 => レシーバなし # Ruby 2.7 以降 => レシーバなし
呼び出されたメソッドが private
メソッドの場合『レシーバ付きだと method_missing
が呼ばれる』のでそれで処理を切り分けるようにしています。
そもそもこの時に method_missing
が呼ばれるのは期待する動作なのかどうか…。
Ruby 2.7 からは self.
付きでも private
メソッドが呼び出せるようになっているのでその部分に差異があります。