2009-11-05 6 views
1

Je travaille sur un site de rails dont j'ai hérité et j'essaie de dépanner un comportement de modèle sous-optimal. J'ai des utilisateurs, des chansons, et songs_download, dont chacun est son propre modèle.Rails Modélisation Question - Relations et Clés primaires

Voici la ligne correspondante du modèle de l'utilisateur:

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

A partir du modèle de chansons:

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

Et à partir du modèle song_downloads:

belongs_to :user 
belongs_to :song 

Voici le code pour créer un nouvel enregistrement song_download lorsqu'un utilisateur télécharge une chanson (dans le contrôleur de chansons):

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

Le problème que je vais avoir est qu'une fois qu'un utilisateur télécharge une chanson, si je tente d'appeler les utilisateurs téléchargés à partir de la console interactive, par, par exemple, en tapant ce qui suit:

Song.find(<some id>).downloaded_users 

Je récupère l'enregistrement complet de l'utilisateur, mais l'identifiant dans l'objet renvoyé est la clé primaire de SongDownload, pas la clé primaire de l'utilisateur. Tous les autres champs sont précis, mais l'ID ne l'est pas.

Je ne suis pas arrivé avec ce schéma de modélisation et il me semble que :has_and_belongs_to_many pourrait être mieux utilisé sans objet SongDownload explicitement modélisé, mais je préfèrerais ne pas réviser la base de code si je peux l'aider. Existe-t-il des moyens de récupérer le bon identifiant d'utilisateur compte tenu du schéma de modélisation actuel?

Merci beaucoup pour votre temps et considération!

Justin

Répondre

1

Le has_many: through est recommandé lorsque la table de jointure a plus de colonnes que simplement deux clés étrangères.

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 

Maintenant, vous pouvez obtenir une liste d'utilisateurs qui ont téléchargé une chanson comme ceci:

Song.find(1).downloaded_users 
5

a et fait partie des relations sont éliminés en faveur a beaucoup: par des relations. À la hausse, vous n'aurez pas besoin de modifier la structure sous-jacente, mais seulement les déclarations de relation dans les modèles Song et User.

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 

maintenant

Song.find(<some id>).users 

Renvoie un tableau d'objets de l'utilisateur qui sont reliés à la chanson sélectionnée dans la table song_downloads.

+0

En plus de cela, votre recommandation devrait être mise en œuvre becaue cette relation HABTM est laid et non la norme de toute façon . Aller avec la relation hmt tue deux oiseaux avec une pierre. – cgr

+0

Cela vaudrait la peine de faire cela. – jonnii

+0

EmFi, merci! Jusqu'ici, tout va bien - vos recommandations sont en place. Juste une chose: chaque fois que j'exécute 'Song.find () .downloaded_users', je récupère un tableau d'associations, pas un tableau d'objets utilisateur. Comment puis-je obtenir le tableau des utilisateurs? – justinbach

Questions connexes