2009-11-05 150 views
1

我正在繼承一個rails站點,並試圖解決一些次優模型行爲。我有用戶,歌曲和songs_download,每個都是它自己的模型。Rails建模問題 - 關係和主鍵

下面是從用戶模型中的相關行:

has_and_belongs_to_many :downloaded_songs, :class_name => 'Song', :join_table => :song_downloads 

從歌曲模式:

has_and_belongs_to_many :downloaded_users, :class_name => 'User', :join_table => :song_downloads 

而且從song_downloads型號:

belongs_to :user 
belongs_to :song 

下面是創建的代碼用戶下載歌曲時的新歌曲下載記錄(在歌曲控制器中):

SongDownload.create(:song_id => @song.id, 
        :user_id => current_user.id, 
        :download_date => Date.today) 

我遇到的問題是,一旦用戶下載一首歌曲,如果我嘗試從交互式控制檯調用下載用戶,比方說,鍵入以下內容:

Song.find(<some id>).downloaded_users 

我找回用戶的完整記錄,但返回對象中的id是SongDownload的主鍵,而不是用戶的主鍵。所有其他字段都是準確的,但ID不是。

我沒有想出這個建模方案,在我看來,:has_and_belongs_to_many可能更適合沒有明確建模的SongDownload對象,但我寧願不檢修代碼庫,如果我可以幫助它。鑑於當前的建模方案,是否有任何方法可以找回正確的用戶ID?

非常感謝您的時間和考慮!

賈斯汀

回答

1

當連接表的列數多於兩個外鍵時,建議使用has_many:through。

class User < ActiveRecord::Base 
    has_many :song_downloads 
    has_many :downloaded_songs, 
      :through => :song_downloads, 
      :source => :song 
end 
class Song < ActiveRecord::Base 
    has_many :song_downloads 
    has_many :downloaded_users, 
      :through => :song_downloads, 
      :source => :user 
end 

現在,你可以得到下載特定的歌曲,像這樣的用戶列表:

Song.find(1).downloaded_users 
5

擁有屬於關係有利於被淘汰的有很多:通過關係。

在好處上,您不需要更改任何底層結構,只需更改歌曲和用戶模型中的關係聲明即可。

class Song < ActiveRecord::Base 

    has_many :song_downloads 
    has_many :users, :through => :song_downloads 

    ... 
end 

class User < ActiveRecord::Base 

    has_many :song_downloads 
    has_many :songs, :through => :song_downloads 

    ... 
end 

現在

Song.find(<some id>).users 

返回其通過song_downloads表連接於所選歌曲的用戶對象的陣列。

+0

最重要的是,你的建議,應實行becaue是HABTM關係是醜陋和非標準反正。與hmt的關係一舉兩得。 – cgr 2009-11-06 00:03:57

+0

這將是值得的努力。 – jonnii 2009-11-06 01:05:26

+0

EmFi,謝謝!到目前爲止,這麼好 - 你的建議已經到位。只有一件事:只要我執行'宋'。找到().downloaded_users',我找回一個關聯數組,而不是一個用戶對象數組。我如何獲得用戶數組? – justinbach 2009-11-06 13:39:23