如何将简单的DSL添加到Ruby类?

时间:2014-10-26 06:36:23

标签: ruby-on-rails ruby

如何实现一个允许我使用DSL注册其他类的类,并且可以在实例化后访问它们,如下例所示:

module Google
  class Search
    def self.run 
      puts :search
    end
  end

  class Map
    def self.run 
      puts :map
    end
  end

  class Calendar
    def self.run 
      puts :calendar
    end
  end
end

class One
  has Google::Search
  has Google::Map

  def perform
    # run through all registered classes, instantiate and then call run on each
  end
end

class Two
  has Google::Calendar

  def perform
    # run through all registered classes, instantiate and then call run on each
  end
end

One.new.peform 
# => 'search'
# => 'map'

One.new.peform 
# => 'calendar'

1 个答案:

答案 0 :(得分:5)

您的初始代码包含多个错误,甚至不会通过ruby解释器。

首先,您需要实现DSL处理程序:

module DSLHandler
  @@classes = {}
  def classes
    @@classes[self.name] ||= []
  end
  def has clazz
    classes << clazz
    puts "registered #{clazz} in #{classes}"
  end
  extend self
end

现在需要了解,因为在类级别调用has,所以在同一级别上执行必须。总结:

class Google ; end

class Google::Search
  def self.run
    puts :search
  end
end

class Google::Map
  def self.run
    puts :map
  end
end

class Google
  extend DSLHandler

  has Google::Search
  has Google::Map

  def self.perform
    classes.each { |clazz| clazz.run }
  end
end

Google.perform

结果如预期:

# ⇒ registered Google::Search in [Google::Search]
# ⇒ registered Google::Map in [Google::Search, Google::Map]
# ⇒ search
# ⇒ map