同一型号的has_many和belongs_to

时间:2012-11-07 21:39:13

标签: ruby-on-rails ruby activerecord

我对rails非常陌生。我试图找出在两个模型之间创建关系的最有效方法:

  1. 用户可以“喜欢”很多歌曲
  2. 一首歌有一个主人。
  3. 这就是我在想的事情。它有意义吗?

    class User < ActiveRecord::Base
        has_many :songs #songs this user has favorited
    end
    
    class Song < ActiveRecord::Base
        belongs_to :user #the user whom submitted this song
    end
    

    我对这种方法的关注是,我不确定对数据库中每首歌进行查询的效率,只是为了弄清楚特定用户拥有哪些歌曲。有没有不同的方式我应该考虑这个?

    顺便说一下,有没有一种方法可以调用属性,而不是它的模型名称。因此,即使模型仍然是“歌曲”,我也可以说User.find(1).songs[0] User.find(1).favorites[0]而不是{{1}}。

3 个答案:

答案 0 :(得分:7)

用户和歌曲模型之间需要2个独立的关系。也就是说,您需要一个“所有者”关系和一个“最喜欢”的关系。 “所有者”关系可以是一个简单的has_many / belongs_to,就像现在一样。 “最喜欢的”关系是多对多关系,需要一个连接表,用作habtm表或具有has_many through关系的第一类模型,如here所述。

通常推荐的方法是使用has_many through,因为它可以让您更好地控制:

class User
  has_many :songs                                            # these are songs 'owned' by the user
  has_many :user_favorite_songs
  has_many :favorite_songs, :through => :user_favorite_songs # these are the favorites
end

class Song
  belongs_to :user
  has_many :user_favorite_songs
end

class UserFavoriteSong
  belongs_to :user
  belongs_to :favorite_song, :class_name => 'Song', :foreign_key => :song_id
end

答案 1 :(得分:2)

这看起来很好。
Rails协会试图最有效 - 不要过早地优化。

您可以为关联名称添加别名:

class User < ActiveRecord::Base
  has_many :favorites, class_name: 'Song'
end

请参阅docs about associations

无论如何,您可能希望查看:inverse_of关联选项。

答案 2 :(得分:1)

我没有测试过这段代码,但你需要这样的东西。

class User < ActiveRecord::Base
  has_and_belongs_to_many :favorites, :class_name => "Song" #user's favorited songs
end

class Song < ActiveRecord::Base
  belongs_to :user #the user who submitted the song
  has_and_belongs_to_many :user, :as => :favorite
end

由于多个用户可以收藏一首歌,因此您需要一个“加入表”

CreateUsersFavorites < ActiveRecord::Migration
  def up
    create_table :users_favorites do |t|
      t.references :user
      t.references :favorite
    end
    create_index :users_favorites, :user_id
    create_index :users_favorites, :favorite_id
  end
  def down
    drop_table :users_favorites
  end
end

此外,我强烈建议您查看rails guide for active record relationships