2009-11-05 108 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