繁体   English   中英

Rails:has_many通过多态关联 - 这会有效吗?

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

一个Person可以有很多Events ,每个Event可以有一个多态Eventable记录。 如何指定PersonEventable记录之间的关系?

以下是我的模型:

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 :eventables, :through => :events

或者我必须像这样拼写它们:

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

如果你看到一种更简单的方法来完成我所追求的目标,我会全都耳朵! :-)

你必须做:

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

另一个选择是使用单表继承(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 方法可能非常有用)

但根据我的经验,随着应用规模的扩大,这是一个更清晰的职责划分。 只是一种需要考虑的模式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM