Rails: has_many through with polymorphic association - will this work?

*爱你&永不变心* 提交于 2019-11-29 19:44:14

You have to do:

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

This will enable you to do this:

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

Another option of this is to use a Single Table Inheritance (STI) or Multi Table Inheritance (MTI) pattern, but that requires some ActiveRecord/DB Table rework, but this may help others still finding this who are designing it for the first time.

Here is the STI method in Rails 3+: Your Eventable concept becomes a class and needs a type column (which rails automatically populates for you).

class Eventable < ActiveRecord::Base
  has_one :event
end

Then, your other two classes inherit from Eventable instead of AR::Base

class Meal < Eventable
end

class Workout < Eventable
end

And your event object is basically the same, just not polymorphic:

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

This may make some of your other layers more confusing, if you've never seen this before and you're not careful. For example, a single Meal object can be accessed at /meals/1 and /eventable/1 if you make both endpoints available in the routes, and you need to be aware of the class you're using when you pull an inherited object (hint: the becomes method may be very useful if you need to override the default rails behavior)

But this is a much cleaner deliniation of responsibilities as apps scale, in my experience. Just a pattern to consider.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!