Модуль Ruby Template - PullRequest
       5

Модуль Ruby Template

2 голосов
/ 20 июля 2009

Предположим, у меня есть семейство связанных модулей:

module Has_Chocolate
   def has_chocolate?
      true
   end
end

module Has_Cake
   def has_cake?
      true
   end
end

. , .

Как мне создать шаблонный модуль Has_ Что-то , где Что-то будет параметром для модуля?

1 Ответ

4 голосов
/ 20 июля 2009

Модули являются константами в их инкапсулирующем контексте, который для верхнего уровня - ядро. Это позволяет нам получить модуль с const_get. Попробуйте это:

module Has_Something
  def has(*items)
    items.each do |item|
      mod = Kernel.const_get("Has_" + item.to_s.capitalize)
      instance_eval { include mod }
    end
  end
end

class Baker
  extend Has_Something
  has :cake
end

class CandyMan
  extend Has_Something
  has :chocolate
end

class ChocolateCake
  extend Has_Something
  has :cake, :chocolate
end

Если вы предпочитаете включить over extension, вы можете сделать это тоже:

module Has_Something
  def self.included(base)
    base.extend HasTemplate
  end

  module HasTemplate
    def has(*items)
      items.each do |item|
        mod = Kernel.const_get("Has_" + item.to_s.capitalize)
        instance_eval { include mod }
      end
    end
  end
end

class Baker
  include Has_Something
  has :cake
end

class CandyMan
  include Has_Something
  has :chocolate
end

class ChocolateCake
  include Has_Something
  has :cake, :chocolate
end

В любом случае этот код одинаков:

steve = Baker.new
bob = CandyMan.new
delicious = ChocolateCake.new
steve.has_cake? && bob.has_chocolate?  # => true
delicious.has_cake? && delicious.has_chocolate?  #=> true

EDIT:

Исходя из вашего комментария, вы ищете способ автоматического создания методов в формате has_ что-то ?. Это еще проще сделать:

module Has_Something
  def has (*items)
    items.each do |item|
      method_name = ('has_' + item.to_s + '?').to_sym
      send :define_method, method_name do
        true
      end
    end
  end
end

class Baker
  extend Has_Something
  has :cake
end

class CandyMan
  extend Has_Something
  has :chocolate
end

class ChocolateCake
  extend Has_Something
  has :cake, :chocolate
end

steve = Baker.new
bob = CandyMan.new
delicious = ChocolateCake.new

steve.has_cake? && bob.has_chocolate?  # => true
delicious.has_cake? && delicious.has_chocolate?  # => true
...