DefinedBy

Advanced DSL and Dynamic class generation for Ruby

When do I is this?

  • If you want to use a DSL to cut down on your code base
  • If you need that DSL to create classes
  • If you have a base class (e.g. Widget) and want to subclass it dozens of times but it's overkill to create separate classes for it manually.
  • Define template classes (default values for subclasses)

All at once

class Widget
  class << self
    def define(&block)
      DefinedBy::DSL(&block).map do |key, value, dsl_block|
        define_class(key, self).new(:name => key.to_s, :description => value)
      end
    end
  end

  attr_accessor :name, :description

  def initialize(attributes = {})
    attributes.each do |key, value|
      self.send("#{key.to_s}=", value)
    end
  end
end

def Widget(&block)
  Widget.define(&block)
end

widgets = Widget do
  widget_a "This widget does X"
  widget_b "This does Y"
end

puts widgets.inspect
#=> [
  #<WidgetA:0x5c3348 @description="This widget does X", @name="widget_a">,
  #<WidgetB:0x5c2970 @description="This does Y", @name="widget_b">
]

http://www.khelll.com/blog/ruby/stackoverflow-cool-ruby-questions-4/