假设我有一个模型Movie。电影可以通过中间模型have_many相互AssociatedMovie。
我怎样才能具体说明两部电影之间关系的性质?对于任何一部电影,这种关系可能是前传/续集,或重拍/原创,或受启发/启发,或相关/相关的,等等。现在,我无法给出关系的名称。
下面是我的模式和关联:
create_table "movies", force: true do |t|
  t.string   "title"
end
create_table "associated_movies", force: true do |t|
  t.integer  "movie_a_id"
  t.integer  "movie_b_id"
end
class Movie < ActiveRecord::Base
  has_many :movies, :through => :associated_movies
end
class AssociatedMovie < ActiveRecord::Base
  has_many :movies
end下面是设置每部电影相关电影的查询:
def movie_associated_movies
  associated_movie_ids = AssociatedMovie.
      where("movie_a_id = ? OR movie_b_id = ?", self.id, self.id).
      map { |r| [r.movie_a_id, r.movie_b_id] }.
      flatten - [self.id]
  Movie.where(id: associated_movie_ids)
end我想我可能需要在movie_a_type和movie_b_type属性中添加AssociatedMovie。但我不知道我怎么能指定哪部电影被附加到哪一种类型。
有人有什么想法吗?
发布于 2015-11-17 08:47:12
使用has_many :through (使用中间模型)已经是半途而废了--这允许您添加任意数量的额外属性。
我认为你的问题归结于你的人际关系,我将在下面解释:
#app/models/movie.rb
class Movie < ActiveRecord::Base
   has_many :associated_movies, foreign_key: :movie_a_id
   has_many :movies, through: :associated_movies, foreign_key: :movie_b_id
end
#app/models/associated_movie.rb
class AssociatedMovie < ActiveRecord::Base
   belongs_to :movie_a, class_name: "Movie"
   belongs_to :movie_b, class_name: "Movie"
end以上将使您可以访问:
@movie = Movie.find params[:id]
@movie.associated_movies #-> collection of records with movie_a and movie_b
@movie.movies #-> all the movie_b objects--
由于您使用的是has_many :through,has_and_belongs_to_many,所以您可以根据需要向联接模型添加尽可能多的属性:

要做到这一点,只需添加一个迁移:
$ rails g migration AddNewAttributes
#db/migrate/add_new_attributes_________.rb
class AddNewAttributes < ActiveRecord::Migration
   def change
      add_column :associated_movies, :relationship_id, :id
   end
end
$ rake db:migrate-
..。如果这有点离题,我很抱歉;但是,我实际上会为您的关系添加一个单独的模型(考虑到您已经预先定义了它们):
#app/models/relationship.rb
class Relationship < ActiveRecord::Base
    #columns id | movie_a_type | movie_b_type | created_at | updated_at
    has_many :associated_movies
end
#app/models/associated_movie.rb
class AssociatedMovie < ActiveRecord::Base
    belongs_to :movie_a, class_name: "Movie"
    belongs_to :movie_b, class_name: "Movie"
    belongs_to :relationship
    delegate :movie_a_type, :movie_b_type, to: :relationship
end这看起来有点臃肿(确实如此),但它将提供扩展性。
您必须添加另一个表,但它最终将为您提供调用以下内容的能力:
@movie.associated_movies.each do |associated|
   associated.movie_a #-> current movie
   associated.movie_b #-> related movie
   associated.movie_a_type #-> "Original"
   associated.movie_b_type #-> "Sequel"
end然后,您将能够使用您将拥有的各种关系预填充Relationship模型。
我可以按要求补充答案。
https://stackoverflow.com/questions/33751858
复制相似问题