2010-10-11 26 views
0

Supposons une association polymorphe, par exemple 'business' et 'staff', les deux étant 'hourable' (ce qui signifie qu'ils ont des heures qui leur sont assignées). Quelle est l'approche recommandée pour que le modèle 'hour' applique les mêmes méthodes aux heures d'un objet métier ou d'un objet personnel?Partage du modèle pour les associations polymorphes

Pour un exemple simple, le modèle « heures » peut contenir:

def self.find_hours_for_id(id) 
    Business.find(id).hours 
    end 

Cependant, je souhaite effectuer cette même méthode sur un membre du personnel, auquel cas la même méthode serait plutôt appeler l'équivalent de

Staff.find(id).hours 

Est-il bon ou mauvais formulaire pour définir le nom du modèle dans la classe de modèle de base:

class BusinessHour < Hour 
    @mymodel = "Business" 
end 

class Hour < ActiveRecord::Base 
    def self.find_hours_for_id(id) 
    @mymodel.constantize.find(id).hours 
    end 
end 

Ensuite, à partir du contrôleur, appelez:

BusinessHour.find_hours_for_id(id) 

est-il une meilleure solution?

Répondre

1

Vous pouvez également utiliser un module, comme cela.

module Hour 
    def hours_by(model) 
    class_eval do 
     def self.find_hours_for_id(id) 
     model.find(id).hours 
     end 
    end 
    end 
end 

class BusinessHour < AR 
    extends Hour 
    hours_by Business 
end 

BusinessHour.find_hours_for_id(id) 
+0

Merci! Diriez-vous que c'est mieux que ce que j'ai fait? Est-ce que ma solution serait acceptable aussi? Juste curieux. – 99miles

+0

votre solution est acceptable. C'est juste une façon différente de faire. Et ma solution fonctionne mieux si vous avez un héritage "multiple" – shingara

1

En supposant, oh par exemple, votre modèle d'objet ressemble à:

class Business < ActiveRecord::Base 
    has_many :hours, :as => :hourable 
end 

class Staff < ActiveRecord::Base 
    has_many :hours, :as => :hourable 
end 

class Hour < ActiveRecord::Base 
    belongs_to :hourable, :polymorphic => true 
end 

class BusinessHour < Hour 
    # etc 
end 

Ensuite, vous avez déjà une référence à la classe dont vous avez besoin dans 'hourable, et vous pouvez ajouter le viseur comme suit :

class Hour < ActiveRecord::Base 
    belongs_to :hourable, :polymorphic => true 

    def self.get_hours_by_hourable_id(id) 
    hourable.class.find(id).hours 
    end 
end 

Juste une suggestion, mais vous pourriez envisager de mettre une validation sur les sous-classes pour garantir que: hourable est le type approprié, tel que:

class BusinessHour < Hour 
    validates :hourable_must_be_business 

    def hourable_must_be_business 
    unless hourable_type == 'Business' 
     self.errors.add_to_base("Hourable for BusinessHour must be Business") 
    end 
    end 
end 
+0

Hmm, c'est à quoi ressemblent mes modèles, cependant quand j'essaie d'accéder à 'hourable' dans le modèle Hour, j'obtiens: "variable locale non définie ou méthode' hourable "pour # " – 99miles

+0

Doh. Oui, c'est un appel d'instance dans une portée de classe. Ma faute. Lemme travaille là-dessus. –

+0

lol ... à la séance de planification pour l'après-midi. Je vais travailler dessus. Problème intéressant La solution méta-module de shingara semble être une bonne option à première vue. –