因此。我有用户和电影。用户观看了一些电影而不是其他电影。我想表达这样的关系:
注意:
我最初的反应是这是has_many :through
关系,例如:
/models/user.rb:
def User
has_many :movies, :through => :unwatched_movies
has_many :movies, :through => :watched_movies
end
/models/movie.rb:
def Movie
has_many :users, :through => :unwatched_movies
has_many :users, :through => :watched_movies
end
但首先,该代码肯定不起作用......
我希望能够查询u.unwatched_movies
(其中u
是User
的一个实例,但似乎与上述情况无关。< / p>
我觉得这与:source
或:as
有关......但我感觉有点失落。我是否正确地认为这是一个3级层次结构,我需要User
,UnwatchedMovieList
/ WatchedMovieList
和Movie
的模型? This question感觉非常接近,但我似乎无法在这种情况下使其发挥作用。
有关如何编写这些模型和迁移的任何帮助都会非常有用。谢谢!
答案 0 :(得分:1)
你正试图建立一种遗漏关系 - “无与伦比的电影”。这不是一个好主意,你应该建立一个电影观看的历史(这是watched_movies)但然后为了无人看,你会想找到所有电影减去观看电影。然后将其粘贴在User中的函数中,如下所示:
def unwatched_movies
Movie.where("id NOT IN ?", self.watched_movies.collect(&:movie_id))
end
答案 1 :(得分:1)
这是我的解决方案
创建这些模型
class User < ActiveRecord::Base
has_many :user_movies
# Use a block to add extensions
has_many :movies, through: :user_movies, source: 'movie' do
# this is an extension
def watched
where('user_movies.watched = ?', true)
end
def unwatched
where('user_movies.watched = ?', false)
end
end
end
class Movie < ActiveRecord::Base
has_many :user_movies
has_many :watchers, through: :user_movies, source: :user do
# users who is an effective watcher
def watchers
where('user_movies.watched = ?', true)
end
# users how marked it but did not watch it yet
def markers
where('user_movies.watched = ?', false)
end
end
end
class UserMovie < ActiveRecord::Base
belongs_to :user
belongs_to :movie
end
class CreateUserMovies < ActiveRecord::Migration
def change
create_table :user_movies do |t|
t.belongs_to :user, index: true
t.belongs_to :movie, index: true
t.boolean :watched, default: false, null: false
t.timestamps null: false
end
add_foreign_key :user_movies, :users
add_foreign_key :user_movies, :movies
end
end
然后查询
@user = User.first
@user.movies.watched
@user.movies.unwatched
@movie = Movie.first
@movie.watchers.watchers
@movie.watchers.markers
答案 2 :(得分:0)
以下一组关联应涵盖您能够明确标记已观看和未观看的电影的用例。它使用名为user_movies
的联接表,其中只包含以下字段:user_id, movie_id, and watched
class User
has_many :unwatched_user_movies, -> { where(watched: false) }, class_name: 'UserMovie'
has_many :unwatched_movies, through: :unwatched_user_movies, class_name: 'Movie'
has_many :watched_user_movies, -> { where(watched: true) }, class_name: 'UserMovie'
has_many :watched_movies, through: :watched_user_movies, class_name: 'Movie'
end
class UserMovie
belongs_to :movie
belongs_to :user
end
class Movie
has_many :user_movies
end