Цепочки ответственности и проблемы alias_method в Ruby
Я пытаюсь реализовать шаблон цепочки ответственности в Ruby и ActiveRecord для полиморфного объекта. У меня есть несколько проблем.
- Иногда я получаю сообщение об ошибке, что метод не определен, когда я пытаюсь alias_method его, я думаю, что это потому, что класс не загружен или что-то, поэтому я просто делаю посылку, чтобы получить метод
- Я получаю кучу бесконечных цепочек, где функция с псевдонимом (original_method) вызывает метод, который вызывает original_method. Мне интересно, если это так, потому что когда вы создаете псевдоним метода, который уже был перезаписан, вы по сути делаете "original_method" копией псевдонима метода.
- В настоящее время я работаю над этим, имея функцию типа "цепочка", возвращающую подкласс 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
Тогда у меня есть объект Setting:
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
1 ответ
Вы, кажется, слишком усложняете. Кажется, вы пытаетесь увидеть, существуют ли api_key и active_days, и если нет, то получите его откуда-то еще.
Вот правильный способ сделать это, предполагая, что api_key и active_days являются столбцами в вашей таблице:
class Setting < ActiveRecord::Base
belongs_to :settable, :polymorphic => true
def api_key
super || settable.next_link.usable_setting.api_key
end
def active_days
super || settable.next_link.usable_setting.active_days
end
end
Вы можете немного изменить его, чтобы сохранить ясность и удалить дубликаты.
class Setting < ActiveRecord::Base
belongs_to :settable, :polymorphic => true
def api_key
super || next_usable_setting.api_key
end
def active_days
super || next_usable_setting.active_days
end
private
def next_usable_setting
settable.next_link.usable_setting
end
end
Так что в этом случае обратите внимание - если у вас есть api_key/active_days, он будет возвращен. В противном случае он будет извлекать usable_setting из next_link. Если у этого есть api_key/active_days, он будет возвращен, в противном случае он получит usable_setting из next_link. И т.п.