开发者

Rails Modeling Question - Relationships and Primary Keys

I'm working on a rails site that I've inherited and am trying to troubleshooting some sub-optimal model behavior. I have use开发者_运维百科rs, songs, and songs_download, each of which is its own model.

Here's the relevant line from the users model:

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

From the songs model:

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

And from the song_downloads model:

belongs_to :user
belongs_to :song

Here's the code to create a new song_download record when a user downloads a song (in the songs controller):

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

The problem I'm having is that once a user downloads a song, if I try to invoke the downloaded users from the interactive console, by, say, typing the following:

Song.find(<some id>).downloaded_users

I get back the complete record of the user, but the id in the returned objected is the primary key of the SongDownload, not the primary key of the User. All of the other fields are accurate, but the ID is not.

I didn't come up with this modeling scheme and it seems to me that :has_and_belongs_to_many might be more appropriately used with no explicitly modeled SongDownload object, but I'd rather not overhaul the codebase if I can help it. Are there any ways to get back the right user id given the current modeling scheme?

Thanks very much for your time and consideration!

Justin


Has and belongs to relationships are being phased out in favour of has many :through relationships.

On the upside you won't need to change any of your underlying structure, just the relationship declarations in the Song and User models.

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

Now

Song.find(<some id>).users

Returns an array of User objects which are joined to the selected song through the song_downloads table.


The has_many :through is recommended when the join table has more columns than simply two foreign keys.

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

Now you can get a list of users that have downloaded a particular song like so:

Song.find(1).downloaded_users
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜