Reputation: 2173
Is there equivalent of python __getattr__
in ruby (for finding methods at least)?
class X(object):
def __getattr__(self, name):
return lambda x: print("Calling " + name + ": " + x)
x = X()
x.some_method("some args")
So it could be something like:
class X
# .. ??? ..
def default_action(method_name, x)
puts "Calling {method_name}: {x}"
end
end
x = X.new()
x.some_method("some args")
Upvotes: 3
Views: 1074
Reputation: 369428
Yes. If an object does not respond to a message, Ruby will send a method_missing
message with the message selector and the arguments to the receiver:
class X
def method_missing(selector, *args, &blk)
puts "The message was #{selector.inspect}."
puts "The arguments were #{args.map(&:inspect).join(', ')}."
puts "And there was #{blk ? 'a' : 'no'} block."
super
end
end
x = X.new
x.some_method('some args', :some_other_args, 42)
# The message was :some_method.
# The arguments were "some args", :some_other_args, 42.
# And there was no block.
# NoMethodError: undefined method `some_method'
x.some_other_method do end
# The message was :some_other_method.
# The arguments were .
# And there was a block.
# NoMethodError: undefined method `some_other_method'
Note that if you define method_missing
, you should also define respond_to_missing?
accordingly. Otherwise you get strange behavior like this:
x.respond_to?(:foo) # => false
x.foo # Works. Huh?
In this particular case, we handle all messages, therefore we can simply define it as follows:
class X; def respond_to_missing?(*) true end end
x.respond_to?(:foo) # => true
Upvotes: 8
Reputation: 80065
class X
def method_missing(sym,*args)
puts "Method #{sym} called with #{args}"
end
end
a = X.new
a.blah("hello","world")
#=> Method blah called with ["hello", "world"]
Upvotes: 5
Reputation: 746
IIRC, you can define method_missing in ruby classes to handle this. Sorry that I can't provide specifics.
Upvotes: 2
Reputation: 65867
class Test
def say
puts "hi"
end
end
and you can invoke say method by
obj = Test.new
obj.send "say"
and checking the method availability using
obj.respond_to? "say"
finally, put together all
if (obj.respond_to? "say")
obj.send "say"
end
Upvotes: -2