我正在使用具有多态关联的ActiveRecord模型,如下所示:
class Reach < ActiveRecord::Base
belongs_to :reachable, :polymorphic => true
end
此模型就像一个代理。我需要做的是将该对象上的所有方法调用转发到关联的对象:reachable
。我认为delegate
在这里没有帮助,因为我必须明确命名我需要委派的所有方法。我需要delegate :all
之类的东西来委托所有方法(不是all
方法)。
答案 0 :(得分:17)
你可以在这里做两件事:
较慢(性能方面)但更简单的方法是使用method_missing:
class Reach < ActiveRecord::Base
def method_missing(method, *args)
return reachable.send(method, *args) if reachable.respond_to?(method)
super
end
end
执行速度更快的方法是动态定义要委派的每个方法:
class Reach < ActiveRecord::Base
[:all, :my, :methods, :here].each do |m|
define_method(m) do |*args|
reachable.send(m, *args)
end
end
end
如果需要,您甚至可以以更动态的方式使用该方法,方法是使用Reach类,找到在其上单独定义的方法,并仅定义Reachable上的方法。我会手工做,因为有些你可能不想包括。
答案 1 :(得分:5)
对于Rails,我做了以下事情:
class User < ApplicationRecord
has_one :member
delegate (Member.new.attributes.keys - User.new.attributes.keys), to: :member
end
- User.new...
不会覆盖User
上的现有属性(例如created_at
)
答案 2 :(得分:1)
我找到了一种使用细化来解决问题的简洁方法。标准库中已经有一个类允许将每个方法调用委托给目标对象。 Delegator
and by extension SimpleDelegator
现在有一种方法可以将SimpleDelegator
插入到继承链中,而无需使用优化直接从它继承:
def self.include_delegator
mod = Module.new do
include refine(SimpleDelegator) { yield if block_given? }
end
self.send :include, mod
end
include_delegator
现在为了利用SimpleDelegator
在一个after initialize回调中设置委托目标,如下所示:
after_initialize do |instance|
__setobj__(instance.reachable)
end
这相当于直接从SimpleDelegator继承并在构造中设置委托,没有手动管理委派的方法,你可以避免使用方法丢失。