I'm creating a presenter base class which is supposed to wrap an ActiveRecord object.
我正在创建一个演示程序基类,它应该封装一个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
For each child class, I would like to be able to dynamically define a method based on a child attribute at initialization, so a ListPresenter like:
对于每个子类,我希望能够在初始化时基于子属性动态地定义一个方法,所以ListPresenter如:
class ListPresenter < BasePresenter
end
should respond to list_id
with the wrapped List object's id.
应该使用包装列表对象的id响应list_id。
How would I do that short of defining it on every child class? I've tried the following in def initialize(object)
, both of which do not work. Would prefer to avoid eval
based approaches if possible as I hear it's a code smell.
除了在每个子类上定义它,我怎么做呢?我在def initialize(object)中尝试过以下方法,这两种方法都不适用。如果可能的话,我宁愿避免使用基于eval的方法,因为我听说这是一种代码味道。
Class approach (adds the method to BasePresenter, not the child classes)
类方法(将方法添加到BasePresenter,而不是子类)
self.class.send(:define_method, "#{object.class.name.underscore}_id") do
@object.id
end
Metaclass approach (unable to access instance variables object
or @object
):
元类方法(无法访问实例变量对象或@object):
class << self
define_method "#{@object.class.name.underscore}_id" do
@object.id
end
end
2 个解决方案
#1
4
Use Class#inherited
hook to dynamically add a method whenever sub-class inherits BasePresenter.
每当子类继承BasePresenter时,使用Class#遗传性的hook动态地添加一个方法。
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
#2
2
I recommend you have a look at Class#inherited
.
我建议您看看Class# inheritance。
You can define this method in your base class and it irate over the inheriting classes' methods...
您可以在基类中定义这个方法,它会激怒继承类的方法……
I'll probably edit this once I'm sitting at my computer, but it's quite straightforward.
当我坐在电脑前的时候,我可能会编辑它,但它非常简单。
#1
4
Use Class#inherited
hook to dynamically add a method whenever sub-class inherits BasePresenter.
每当子类继承BasePresenter时,使用Class#遗传性的hook动态地添加一个方法。
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
#2
2
I recommend you have a look at Class#inherited
.
我建议您看看Class# inheritance。
You can define this method in your base class and it irate over the inheriting classes' methods...
您可以在基类中定义这个方法,它会激怒继承类的方法……
I'll probably edit this once I'm sitting at my computer, but it's quite straightforward.
当我坐在电脑前的时候,我可能会编辑它,但它非常简单。