Rails: has_many grâce à l’association polymorphe – ça va marcher?

Une Person peut avoir plusieurs Events et chaque Event peut avoir un enregistrement polymorphe Eventable . Comment spécifier la relation entre la Person et l’enregistrement Eventable ?

Voici les modèles que j’ai:

 class Event  true end class Meal  eventable end class Workout  eventable end 

La question principale concerne la classe Person :

 class Person  :events # is this correct??? end 

Dois-je dire has_many :eventables, :through => :events comme je l’ai fait ci-dessus?

Ou dois-je les épeler tous ainsi:

 has_many :meals, :through => :events has_many :workouts, :through => :events 

Si vous voyez un moyen plus facile d’accomplir ce que je suis après, je suis tout ouïe! 🙂

Tu dois faire:

 class Person < ActiveRecord::Base has_many :events has_many :meals, :through => :events, :source => :eventable, :source_type => "Meal" has_many :workouts, :through => :events, :source => :eventable, :source_type => "Workout" end 

Cela vous permettra de le faire:

 p = Person.find(1) # get a person's meals p.meals.each do |m| puts m end # get a person's workouts p.workouts.each do |w| puts w end # get all types of events for the person p.events.each do |e| puts e.eventable end 

Une autre option consiste à utiliser un modèle STI (Single Table Inheritance) ou MTI (Multi Table Inheritance), mais cela nécessite certaines retouches de table ActiveRecord / DB, mais cela peut aider d’autres utilisateurs à le trouver pour la première fois.

Voici la méthode STI dans Rails 3+: Votre concept Eventable devient une classe et nécessite une colonne de type (quels rails se remplissent automatiquement pour vous).

 class Eventable < ActiveRecord::Base has_one :event end 

Ensuite, vos deux autres classes héritent de Eventable au lieu de AR :: Base

 class Meal < Eventable end class Workout < Eventable end 

Et votre object événement est fondamentalement le même, mais pas polymorphe:

 class Event < ActiveRecord::Base belongs_to :person belongs_to :eventable end 

Cela peut rendre certaines de vos autres couches plus confuses, si vous ne les avez jamais vues auparavant et que vous ne faites pas attention. Par exemple, vous pouvez accéder à un seul object Meal /eventable/1 /meals/1 et /eventable/1 si vous rendez les deux /eventable/1 extrémité disponibles dans les itinéraires et que vous devez connaître la classe que vous utilisez lorsque vous extrayez un object hérité ( indice: la méthode becomes très utile si vous devez remplacer le comportement de rails par défaut)

Mais il s’agit d’une délimitation des responsabilités beaucoup plus nette que celle des applications, selon mon expérience. Juste un motif à considérer.