J'essaie d'implémenter le modèle de chaîne de responsabilité dans Ruby et ActiveRecord pour un objet polymorphe. J'ai quelques problèmes.Problèmes de chaîne de responsabilité et alias_method dans Ruby
- Parfois, je reçois une erreur qu'une méthode n'est pas définie lorsque je tente de alias_method, je pense que cela est parce que la classe n'est pas chargé ou quelque chose donc je fais un explicity envoyer pour obtenir la méthode
- Je reçois un tas de chaînes infinies où la fonction aliasée (original_method) appelle la méthode qui appelle original_method. Je me demande si c'est parce que quand vous alias une méthode qui a déjà été écrasée, vous faites essentiellement "original_method" une copie de la méthode aliasée.
- Je travaille actuellement autour de cela en ayant une fonction comme "chained" retourner une sous-classe de Setting avec toutes les méthodes définies mais curieux de savoir pourquoi il y avait tant de problèmes avec alias_method droit dans la classe.
Voici un exemple:
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
Ensuite, j'ai un objet Cadre:
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
Hey, cette réponse est géniale mais je pense que le principal problème que j'avais était de définir les méthodes métamagiquement. La raison pour laquelle je veux le faire est que j'ai beaucoup de fonctions chaînées et en tant que programmeur, je préfère passer 10 heures à essayer d'éviter la frappe au lieu de 2 heures en tapant tout. J'ai fini par faire En créant une classe séparée qui représentait le chaînage, je pense qu'il était difficile de le faire dans activeecord en raison de la façon dont il crée ses propres fonctions alias. – David
Si vous voulez le faire comme par magie, tout ce que vous avez à faire est: '[: api_key,: active_days] .each {| meth | define_method (meth) {super || next_usable_setting.send (meth)}} '. Mais franchement, je préfère les définir séparément, parce que c'est plus agréable. –