Object#method and dynamic responders
-
03-07-2021 - |
Frage
I have a Ruby object (an ActiveRecord object, specifically) named User
. It responds to methods like find_by_id
, find_by_auth_token
, etc. However, these aren't methods that are defined via def
or define_method
. Instead, they are dynamic methods that are handled via method_missing
.
I'd like to obtain a reference to one of these methods via Object#method
, e.g.:
User.method(:find_by_auth_token)
It doesn't look like this works though. The best solution I've come up with is:
proc { |token| User.find_by_auth_token(token) }
Is there any other way around using such a wrapper method as this? Am I really unable to use Object#method
for dynamic methods?
Lösung
The simplest answer is "no"—the only way to guarantee in general that Object#method(:foo)
will return an instance of Method
is by defining a method named foo
on the object.
The more complected answer is that you can coerce Object#method(:foo)
into returning an instance of Method
by overriding Object#respond_to_missing?
s.t. it returns true
when given :foo
. For example:
class User
def respond_to_missing?(method_name, include_private = false)
method_name.to_s.start_with?('find_by_')
end
end
m = User.new.method(:find_by_hackish_means)
# => #<Method: User#find_by_hackish_means>
(It's up to you to ensure that the method is actually defined):
m.call
# => NoMethodError: undefined method `find_by_hackish_means' for #<User:0x123>