2010-11-16 132 views
2

我有一個國家喜好的應用程序。用戶將有兩種國家偏好 - 事件和研究。未來可能會有更多。我更傾向於使用2個表來代表使用STI的情況。爲了做到這一點,我優雅地配置Rails有點麻煩。我可以破解它,但我寧願通過Rails約定來做到這一點。我想要的是這樣的:如何在Rails中兩次加入相同的兩個模型?

class User < ActiveRecord::Base 
    has_many event_countries, :through => :event_countries, :class_name => 'Country' 
    has_many research_countries, :through => :research_countries, :class_name => 'Country' 
end 

class EventCountry < ActiveRecord::Base 
    belongs_to :country 
    belongs_to :user 
end 

class ResearchCountry < ActiveRecord::Base 
    belongs_to :country 
    belongs_to :user 
end 

class Country < ActiveRecord::Base 
... 
end 

雖然這並不奏效。鑑於這個「僞代碼」是否有人知道如何在Rails中實際實現?

回答

5

我想你要去宣佈他們錯了,因爲這應該正常工作。這就是:through指令是什麼:

class User < ActiveRecord::Base 
    has_many :event_countries 
    has_many :countries_with_events, 
    :through => :event_countries, 
    :source => :country 

    has_many :research_countries 
    has_many :countries_with_researches, 
    :through => :research_countries, 
    :source => :country 
end 

class EventCountry < ActiveRecord::Base 
    belongs_to :country 
    belongs_to :user 
end 

class ResearchCountry < ActiveRecord::Base 
    belongs_to :country 
    belongs_to :user 
end 

class Country < ActiveRecord::Base 
    # ... 
end 

很多的尷尬來自於你所選擇的表的標籤。雖然乍看起來似乎是合理的,但是使用它們的方式最終會使它們變得困難。

您可能需要調用research_countriesuser_research_countries,這樣的關係名稱可以是user.research_countries作爲:through

class User < ActiveRecord::Base 
    has_many :user_event_countries 
    has_many :event_countries, 
    :through => :user_event_countries, 
    :source => :country 

    has_many :user_research_countries 
    has_many :research_countries, 
    :through => :user_research_countries, 
    :source => :country 
end 

class UserEventCountry < ActiveRecord::Base 
    belongs_to :country 
    belongs_to :user 
end 

class UserResearchCountry < ActiveRecord::Base 
    belongs_to :country 
    belongs_to :user 
end 

class Country < ActiveRecord::Base 
    # ... 
end 

您可以通過添加一個字段用戶國家關聯表進一步重構這一點,包括一個或多個旗幟,在這種情況下,這將是研究或事件或任何您需要以後:

class User < ActiveRecord::Base 
    has_many :user_countries 
    has_many :event_countries, 
    :through => :user_countries, 
    :source => :country, 
    :conditions => { :event => true } 
    has_many :research_countries, 
    :through => :user_countries, 
    :source => :country, 
    :conditions => { :research => true } 
end 

class UserCountry < ActiveRecord::Base 
    belongs_to :country 
    belongs_to :user 

    # * column :event, :boolean 
    # * column :research, :boolean 
end 

class Country < ActiveRecord::Base 
    # ... 
end 
+0

真棒的答案。我同意你提到的命名約定。其實這是他們在我的應用程序是如何創建的,但我縮短了它的問題。對於如何重構這也是一個很好的建議。不知道是否比只有「研究」或「事件」的類型列更好,但我想你可以使用該方法可能會導致一些(很少)重複的數據。 – Tony 2010-11-16 16:20:34

+0

在有關用戶和國家的單個表中有N個布爾列可能比有N個關係表的效率高很多。作爲副作用,這也使得查找用戶在同一個國家進行事件並進行研究的情況更容易。 – tadman 2010-11-16 17:30:24

相關問題