Ruby 中的责任链和 alias_method 问题
我正在尝试在 Ruby 和 ActiveRecord 中为多态对象实现责任链模式。我有一些问题。
- 有时,当我尝试使用 alias_method 时,我会收到一个错误,指出方法未定义,我认为这是因为该类未加载或其他原因,所以我明确地执行发送来获取该方法,
- 我得到了一堆无限链,其中别名函数(original_method)调用调用original_method的方法。我想知道这是否是因为当您为已被覆盖的方法添加别名时,您本质上是在使“original_method”成为别名方法的副本。
- 我目前正在解决这个问题,方法是让像“chained”这样的函数返回一个带有所有定义方法的Setting子类,但很好奇为什么类中的alias_method存在这么多问题。
这是一个例子:
class Hospital
has_one :setting, :as => :settable
belongs_to :administrative_area
def next_link
adminstrative_area
end
def usable_setting
setting ? setting : next_link.usable_setting
end
end
然后,我有一个设置对象:
class Setting < ActiveRecord::Base
belongs_to :settable, :polymorphic => true
def chained
%w(api_key active_days).each do |method|
# this is here because otherwise the method isn't defined,
# it's almost as while it's going up, the metaclass doesn't have the columns
# until it loads, probably will be fixed if we cache classes
self.send method.to_sym
(class << self; self; end).class_eval do
define_method method do |*args|
alias_method "original_#{method}", method
my_setting = send("original_#{method}")
if my_setting.nil? or my_setting.empty?
settable.next_link.usable_setting.chained.send(method)
else
return my_setting
end
end
end
end
self
end
end
I'm trying to implement the chain of responsibility pattern in Ruby and ActiveRecord for a polymorphic object. I'm having a few problems.
- Sometimes I get an error that a method is not defined when I try to alias_method it, I think this is because the class isn't loaded or something so I explicity do a send to get the method
- I get a bunch of infinite chains where the aliased function (original_method) calls method which calls original_method. I'm wondering if this is because when you alias a method that's already been overwritten, you're in essence making "original_method" a copy of the aliased method.
- I'm currently working around this by having a function like "chained" return a sub-class of Setting with all the defined methods but curious why there were so many problems with alias_method right in the class.
Here's an example:
class Hospital
has_one :setting, :as => :settable
belongs_to :administrative_area
def next_link
adminstrative_area
end
def usable_setting
setting ? setting : next_link.usable_setting
end
end
Then, I have a Setting object:
class Setting < ActiveRecord::Base
belongs_to :settable, :polymorphic => true
def chained
%w(api_key active_days).each do |method|
# this is here because otherwise the method isn't defined,
# it's almost as while it's going up, the metaclass doesn't have the columns
# until it loads, probably will be fixed if we cache classes
self.send method.to_sym
(class << self; self; end).class_eval do
define_method method do |*args|
alias_method "original_#{method}", method
my_setting = send("original_#{method}")
if my_setting.nil? or my_setting.empty?
settable.next_link.usable_setting.chained.send(method)
else
return my_setting
end
end
end
end
self
end
end
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
你似乎过于复杂化了。似乎您正在尝试查看 api_key 和 active_days 是否存在,如果不存在,请从其他地方获取它。
这是正确的方法,假设 api_key 和 active_days 是表中的列:
您可以对其进行一些重构以保持清晰并删除重复。
因此,在这种情况下请注意 - 如果您有 api_key/active_days 可用,它将被返回。否则,它将从 next_link 获取 usable_setting。如果那个有 api_key/active_days,它将被返回,否则它将从 next_link 获取 usable_setting。 ETC。
You seem to be overcomplicating. Seems that you're trying to see if api_key and active_days exists, and if not, get it from somewhere else.
Here's the right way to do it, assuming that api_key and active_days are columns in your table:
You can refactor it a bit to keep clarity and remove duplication.
So in this case notice — if you have api_key/active_days available, it will get returned. Otehrwise, it will go fetch usable_setting from next_link. If that one has api_key/active_days, it will get returned, otherwise it will fetch usable_setting from next_link. Etc.