Ruby Metaprogramming:基于子实例属性动态定义方法

我正在创建一个presenter基类,它应该包装一个ActiveRecord对象。

class BasePresenter def initialize object @object = object end def method_missing(*args, &block) @object.send(*args, &block) end def self.wrap collection collection.map { |item| new item } end end 

对于每个子类,我希望能够在初始化时基于子属性动态定义方法,因此ListPresenter类似于:

 class ListPresenter < BasePresenter end 

应该使用包装的List对象的id响应list_id

如何在每个儿童class上定义它? 我在def initialize(object)尝试了以下内容,两者都不起作用。 如果可能的话,我宁愿避免使用基于eval的方法,因为我听到这是一种代码味道。

类方法(将方法添加到BasePresenter,而不是子类)

 self.class.send(:define_method, "#{object.class.name.underscore}_id") do @object.id end 

元类方法(无法访问实例变量object@object ):

 class << self define_method "#{@object.class.name.underscore}_id" do @object.id end end 

使用Class#inherited hook在子类inheritanceBasePresenter时动态添加方法。

 class BasePresenter def self.inherited(sub_klass) sub_klass.send(:define_method, "#{sub_klass.name.underscore.split("_")[0...-1].join("_")}_id") do instance_variable_get("@object").id end end end class ListPresenter < BasePresenter end # Sending a rails model object below l = ListPresenter.new(User.first) l.list_id #=> 1 

我建议你看看Class#inherited

您可以在基类中定义此方法,并对inheritance类的方法进行评估…

我可能会在我坐在电脑前编辑这个,但这很简单。