我正在创建一个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
。
如何在每个儿童班上定义它?我在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
答案 0 :(得分:4)
当子类继承BasePresenter时,使用Class#inherited
挂钩动态添加方法。
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
答案 1 :(得分:2)