Reputation: 47
I've got a module called AB. Right now it looks something like this:
module AB
extend self
def some_method(hash)
....
end
....
end
We use it like this: AB.some_method(:thing=>:whatever,:etc=>'you get the idea'). There are about a half-dozen strings that the user has to pass in that I'd like to turn into dynamic methods so that instead of AB.some_method(:thing => :whatever...) They'd just call AB.whatever(...) or AB::whatever(...). I thought I could do this with method_missing, but I guess I don't get it. I did something like this:
module AB
def method_missing(name,*args)
super unless THINGS.include?(name.to_s)
...
end
end
But I never get into that method when trying to call AB::whatever. I thought about looping over THINGS and using define_method, but I wasn't sure how to define methods that take arguments.
Any help appreciated.
Upvotes: 1
Views: 1449
Reputation: 2621
The problem in your second code example is that the method_missing
ought to be declared as self.method_missing
. The following works as expected:
module AB
THINGS = %w(whatever)
def self.method_missing(name, *args)
super unless THINGS.include?(name.to_s)
"responding to #{name}"
end
end
p AB.whatever #=> "responding to whatever"
p AB.something #=> NoMethodError
Upvotes: 4
Reputation: 44080
I think you have two different approaches here you can use, one is defining methods dynamically, another is relying on method_missing
. Here are examples of both:
# first approach, define methods
class MyClassDefine
def some_method args
p args
end
[:foo,:bar].each do |name|
define_method name do |args|
# assume args is a hash, fix me
some_method args.merge({:thing => name})
end
end
end
# second approach, use method_missing
class MyClassMissing
def some_method args
p args
end
def method_missing name, args
super unless [:foo, :bar].include? name
# again, assuming argument is a hash
some_method args.merge(:thing => name)
end
end
mcd = MyClassDefine.new
mcd.foo :etc => 'you get idea'
#=> {:etc=>"you get idea", :thing=>:foo}
mcm = MyClassMissing.new
mcm.foo :etc => 'you get idea'
#=> {:etc=>"you get idea", :thing=>:foo}
What's left to do here is cover the cases when the methods are passed something else than a hash, as an argument.
Upvotes: 0