In this question:
How to list all methods for an object in Ruby?
You can call foo.methods
and get all methods. But this does not get all methods. Example in Rails, with ActiveStorage:
Image.first.specimens.first.methods.include?(:variant)
# => false
Image.first.specimens.first.respond_to?(:variant)
# => true
Image.first.specimens.first.variant
Traceback (most recent call last):
1: from (irb):3
ArgumentError (wrong number of arguments (given 0, expected 1))
Image.first.specimens.first.method(:variant)
# => #<Method: ActiveStorage::Attachment(id: integer, name: string, record_type: string, record_id: integer, blob_id: integer, created_at: datetime)#variant>
Given that an ArgumentError is being raised, it respond_to?
s, and I can grab the method, it does have the variant method. But it is not shown with .methods
. How can I see a full list of methods?
Maybe you missed the last paragraph in the accepted answer of linked post How to list all methods for an object in Ruby?:
Added Note that :has_many does not add methods directly. Instead, the ActiveRecord machinery uses the Ruby method_missing and responds_to techniques to handle method calls on the fly. As a result, the methods are not listed in the methods method result.
To make it clearer what happens a code example:
class Foo
def hello
puts 'Hello'
end
def method_missing(name, *args, &block)
case name
when :unknown_method
puts "handle unknown method %s" % name # name is a symbol
else
super #raises NoMethodError unless there is something else defined
end
end
end
foo = Foo.new
p foo.respond_to?(:hello) #-> true
p foo.respond_to?(:unknown_method) #-> false
foo.unknown_method #-> 'handle unknown method unknown_method'
foo.another_unknown_method #-> Exception
The method unknown_method
is never defined, but there is a method to handle unknown methods. So the class makes the impression of an existing method, but there is none.
Maybe How can I get source code of a method dynamically and also which file is this method locate in helps the get information about the content:
Foo.instance_method(:method_missing).source_location
When you define your own method_missing
, then you should also change the behaviour of respond_to?
with respond_to_missing?
def respond_to_missing?(method, *)
return method == :unknown_method || super
#or if you have a list of methods:
#~ return %i{unknown_method}.include?(method) || super
#or with a regex for
#~ method =~ /another_(\w+)/ || super
end
end
See also `respond_to?` vs. `respond_to_missing?` for details.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With