Ruby has different meta programming techniches to do this kind of stuff.
First we need our variable method
class DB
def get_persons_with_x_things(x)
res = []
persons.each do |person|
if person.number_of_things == x
res << person
end
end
return res
end
end
define_method
If there is a finite number of x s. We could use define_method
to create all this methods. define_method
creates a method. The first argument is the name of the method, the seccond argument or the given block is the stuff, which get s executed when the method is called.
This way, you don t realy create such method s, but It will look for the user if he calls it, as if it existed. But if the user relies on Object#methods
and such, he will never see your inifinite number of fake methods.
class DB
99.times do |i|
define_method("get_persons_with_#{i}_things") do
get_persons_with_x_things(i)
end
end
end
method_missing
If there is an infinite numbor of x s method_missing
would be better suited for this Task. If someone tries to call a method which does not exist, method_missing
is executed instead. The first argument for method_missing
is the method name as symbol, the following arguments are the original arguments.
class DB
def method_missing(name, *args)
case name.to_s
when /^get_persons_with_(d+)_things$/
get_persons_with_x_things($1.to_i)
else
super(name, *args)
end
end
end
method_missing and send
To not use static regexe would be even cooler. But this could have some security implications. The method send
I use here, calls a method by it s name.
class DB
def method_missing(name, *args)
name.to_s=~ /d+/
# always be carefull with $ variables, they are global for this thread, so save everything as fast as you can
new_name= "#{$`}x#{$ }"
number= $1.to_i
if method_defined?(new_name)
send(new_name, number)
else
super(name, *args)
end
end
end