2

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

  1. 用户可以“收藏”许多歌曲
  2. 一首歌有一个所有者。

这就是我想做的事情。是否有意义 ?

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]

4

3 回答 3

7

您需要在 User 和 Song 模型之间建立 2 个独立的关系。也就是说,您需要一个“所有者”关系和一个“最喜欢”关系。'owner' 关系可以是一个简单的 has_many/belongs_to,就像你现在拥有的那样。“最喜欢的”关系是多对多的,需要一个连接表,用作表或具有此处解释habtm的关系的第一类模型。has_many through

通常推荐的方法是使用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
于 2012-11-07T21:44:23.093 回答
2

这看起来非常好。
Rails 关联尽量提高效率——不要过早优化。

您可以为关联的名称起别名,如下所示:

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

请参阅有关关联的文档

无论如何,关于性能,您可能想看看:inverse_of关联选项。

于 2012-11-07T21:47:56.077 回答
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 指南

于 2012-11-07T21:51:40.567 回答