Person
可以有多个Events
,每个Event
可以有一个多态Eventable
记录。如何指定Person
和Eventable
记录之间的关系?
以下是我的模特:
class Event < ActiveRecord::Base
belongs_to :person
belongs_to :eventable, :polymorphic => true
end
class Meal < ActiveRecord::Base
has_one :event, :as => eventable
end
class Workout < ActiveRecord::Base
has_one :event, :as => eventable
end
主要问题涉及Person
类:
class Person < ActiveRecord::Base
has_many :events
has_many :eventables, :through => :events # is this correct???
end
我是否像上面那样说has_many :eventables, :through => :events
?
或者我必须像这样拼写它们:
has_many :meals, :through => :events
has_many :workouts, :through => :events
如果你看到一种更简单的方法来完成我所追求的目标,我会全都耳朵! : - )
答案 0 :(得分:69)
你必须这样做:
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
这将使您能够这样做:
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
答案 1 :(得分:1)
另一个选择是使用单表继承(STI)或多表继承(MTI)模式,但这需要一些ActiveRecord / DB表返工,但这可能有助于其他人仍然发现这是为谁设计它第一次。
以下是Rails 3+中的STI方法:
您的 Eventable 概念成为一个类,需要一个type
列(rails会自动为您填充)。
class Eventable < ActiveRecord::Base
has_one :event
end
然后,你的另外两个类从Eventable继承而不是AR :: Base
class Meal < Eventable
end
class Workout < Eventable
end
你的事件对象基本相同,只是不是多态的:
class Event < ActiveRecord::Base
belongs_to :person
belongs_to :eventable
end
这可能会让你的其他一些层面更加混乱,如果你以前从未见过这样,你就不会小心了。例如,如果您在路线中提供两个端点,则可以在/meals/1
和/eventable/1
访问单个Meal对象,并且您需要知道您在拉动时使用的课程一个继承的对象(提示:如果你需要覆盖默认的rails行为,becomes
method可能非常有用。)
但根据我的经验,随着应用扩展,这是一个更清晰的职责划分。只是一种需要考虑的模式。