multiple models in Rails with a shared interface
I'm not sure of the best structure for a particular situation in Rails. We have several types of workshops. The administration of the workshops is the same regardless of workshop type, so the data for the workshops is in a single model. We collect feedback from participants about the workshops, and the questionnaire is different for each type of workshop. I want to access the feedback about the workshop from the workshop model, but the class of the associated model will depend on the type of workshop. If I was doing this in something other than Rails, I would set up an abstract class for WorkshopFeedback, and then have subclasses for each type of workshop: WorkshopFeedbackOne, WorkshopFeedbackTwo, WorkshopFeedbackThree. I'm unsure how to best handle this with Rails.
I currently have:
class Workshop < ActiveRecord::Base
has_many :workshop_feedbacks
end
class Feedback < ActiveRecord::Base
belongs_to开发者_StackOverflow社区 :workshop
has_many :feedback_ones
has_many :feedback_twos
has_many :feedback_threes
end
class FeedbackOne < ActiveRecord::Base
belongs_to :feedback
end
class FeedbackTwo < ActiveRecord::Base
belongs_to :feedback
end
class FeedbackThree < ActiveRecord::Base
belongs_to :feedback
end
This doesn't seem like to the cleanest way to access the feedback from the workshop model, as accessing the correct feedback will require logic investigating the Workshop type and then choosing, for instance, @workshop.feedback.feedback_one.
Is there a better way to handle this situation? Would it be better to use a polymorphic association for feedback? Or maybe using a Module or Mixin for the shared Feedback interface?
Note: I am avoiding using Single Table Inheritance here because the FeedbackOne, FeedbackTwo, FeedbackThree models do not share much common data, so I would end up with a large sparsely populated table with STI.
I think the best solution is create an abstract class Workshop, and 3 subclasses Workshop1, Workshop2 and Workshop3.
Hence, each will have its set of feedbacks, Feedback1 to Workshop1, Feedback2 to Workshop2, ...
You can change the declaration in the subclasses as follows:
class Workshop1 < Workshop
has_many :feedbacks, :class_name => "Feedback1"
end
class Feedback1 < ActiveRecord::Base
belongs_to :workshop, :class_name => "Workshop1"
end
And in your application can use workshop.feedbacks and and feedback.workshop no matter what class the instance of the Workshop or Feedback belongs.
EDIT: You have three types of workshop with information in common, but each workshop has a specific kind of feedback. So it's bestter to use STI for Workshop, and not for Feedback.
You can subclass your models, like so:
class Workshop < ActiveRecord::Base
has_many :feedback_ones
has_many :feedback_twos
has_many :feedback_threes
#has_many :feedbacks # This MIGHT work, but is untested. I'm not at a dev setup to try.
end
class Feedback < ActiveRecord::Base
belongs_to :workshop
has_many :feedback_ones
has_many :feedback_twos
has_many :feedback_threes
end
class FeedbackOne < Feedback
belongs_to :feedback
end
class FeedbackTwo < Feedback
belongs_to :feedback
end
class FeedbackThree < Feedback
belongs_to :feedback
end
This is likely a better solution, and is cleaner. Your Feedback
table needs to have a type
column, which it uses to use one table for multiple classes. This blog post gives a good basic introduction to the concept of Single Table Inheritance.
精彩评论