如何命名两条记录之间的关系?
How can I name the relationship between two records?
假设我有一个模型 Movie
。电影可以 have_many 通过中介模型 AssociatedMovie
。
如何指定两部电影之间关系的性质?对于任何给定的电影对,关系可能是 prequel/sequel,或 remake/original,或 inspired/inspired by,或 related/related,等等。现在,我无法给出关系名称。
这是我的架构和关联:
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
。但我不确定如何指定哪部电影附加到哪种类型。
有人有什么想法吗?
您已经完成了 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
、rather than 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
这可能看起来有点臃肿(确实如此),但它将提供可扩展性。
您必须添加另一个 table,但它最终会为您提供调用以下内容的能力:
@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
模型。
我可以根据需要补充答案。
假设我有一个模型 Movie
。电影可以 have_many 通过中介模型 AssociatedMovie
。
如何指定两部电影之间关系的性质?对于任何给定的电影对,关系可能是 prequel/sequel,或 remake/original,或 inspired/inspired by,或 related/related,等等。现在,我无法给出关系名称。
这是我的架构和关联:
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
。但我不确定如何指定哪部电影附加到哪种类型。
有人有什么想法吗?
您已经完成了 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
、rather than 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
这可能看起来有点臃肿(确实如此),但它将提供可扩展性。
您必须添加另一个 table,但它最终会为您提供调用以下内容的能力:
@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
模型。
我可以根据需要补充答案。