簡體   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