Frank Koehl Frank Koehl - 5 months ago 10
Ruby Question

Define method calls for class declarations, a la Rails

I'm building a domain-specific hierarchical inheritance structure similar to ActiveRecord, i.e. I have a

Base
class, and then
n
children classes declared under
Base
.

I'm currently declaring specifics in the children as constants, and then calling those from the shared methods in the
Base
class, but it's getting unwieldy. I would like to implement the Rails style of declaring class-specific, instantiated values via method calls.

If you're familiar Rails, I'm essentially trying to duplicate the generic structure of
has_many
/
belongs_to
from ActiveRecord, or
before_action
from ActionPack.

A simplistic, contrived example of what I'm trying to accomplish...

class Widget < Base

important_value :foo, :bar

end

widget = Widget.new
widget.foo
# => :bar


If someone can explain to me what to put in class
Base
to achieve the above, I'll be well on my way.

Answer
class Base 
  class << self
    def important_value(key, value)
      # define method named `key` which returns `value`
      define_method(key) { value } 
    end 
  end 
end 

class Widget < Base 
  important_value :foo, :bar 
end 

Widget.new.foo # => :bar

Or, if the number of "important value" methods are small and known beforehand:

class Base 
  def foo 
    self.class.foo 
  end 

  class << self
    attr_reader :foo 

    def important_value(key, value)
      self.instance_variable_set(:"@#{key}", value)
    end 
  end 
end 

class Widget < Base 
  important_value :foo, :bar 
end 

Widget.new.foo # => :bar