【问题标题】:Rails: has_many through with polymorphic association - will this work?Rails:has_many 通过多态关联——这行得通吗?
【发布时间】:2011-10-23 06:03:47
【问题描述】:

一个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 =&gt; :events吗?

或者我必须像这样拼写出来:

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

如果您发现了一种更简单的方法来完成我所追求的目标,我会全力以赴! :-)

【问题讨论】:

  • +1 用于提出一个没有 75 行代码且仅与您的特定项目相关的问题。

标签: ruby-on-rails activerecord has-many-through polymorphic-associations


【解决方案1】:

你必须这样做:

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

【讨论】:

    【解决方案2】:

    另一种选择是使用单表继承 (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 对象,并且在拉取继承对象时需要注意您正在使用的类(提示: becomes method 如果您需要覆盖默认的 rails 行为,可能会非常有用)

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

    【讨论】:

    • 虽然 STI 在某些情况下可能有用,但我认为假设它在这里是正确的解决方案有点冒昧,而且它有损于问题的目的——有很多非常有效的对在同一个表中没有意义的模型使用多态关联的理由!
    • 我没有假设——我只是提供了另一种选择。
    猜你喜欢
    • 1970-01-01
    • 2014-01-26
    • 2012-01-14
    • 1970-01-01
    • 1970-01-01
    • 2011-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多