CD-RUM CD-RUM - 4 months ago 8
Ruby Question

Ruby: metaprogramming methods based in model attribute

I'm trying to expose some methods to a class based on the values in its order attribute, which can be something like

['top', 'bottom', 'right', 'lower-right']
.

First, my class deletes from that array anything that responds blank like so:

def order
order.split(' ').delete_if do |o|
send(o).blank? if respond_to? o
end
end


After that, I want to "expose"
top
(for example's sake) as a method for the class. I've tried stuff like this in the
initialize
method:

order.each do |o|
V1_ATTRIBUTES << o.to_sym
define_method(o) do |a|
send(a).blank? ? '' : send(a)
end
end


But
o
isn't defined when the class isn't instantialised, a la:

<NameError: undefined local variable or method `o' for #<Class:#<APIDocument:0x007fb8123609f8>>>


Anyone have any success with a better way to get this result?

Note: I know it's not great practice allowing the user to write instance method names, but in this case security and breakages aren't a concern.

Answer

You can define singleton methods (per-object methods).

def order
  orders.split(' ').map{|o| send(o)}.compact.each do |o| 
    singleton_class.send(:define_method, o) do
      send(o).to_s
    end
  end
end

But as you can see, this only messes up your code. So don't abuse metaprogramming, use it wisely.

Comments