Rails 7:演员自关联多对多模型查询报错排查
解决Actor关联报错并实现合作演员及影片查询功能
一、修复关联报错
报错根源是Actor模型中的has_many :actor_partners默认会在actor_partners表中查找actor_id字段,但你的表中只有actor1_id和actor2_id。需要拆分关联并明确指定外键:
修改actor.rb中的关联部分:
class Actor < ApplicationRecord # ... 其他关联和代码 # 作为actor1的合作关系 has_many :actor_partners_as_actor1, class_name: 'ActorPartner', foreign_key: 'actor1_id', dependent: :destroy # 作为actor2的合作关系 has_many :actor_partners_as_actor2, class_name: 'ActorPartner', foreign_key: 'actor2_id', dependent: :destroy # 获取作为actor1时的合作演员(actor2) has_many :partners_as_actor1, through: :actor_partners_as_actor1, source: :actor2 # 获取作为actor2时的合作演员(actor1) has_many :partners_as_actor2, through: :actor_partners_as_actor2, source: :actor1 end
这样就解决了Unknown column 'actor_partners.actor_id'的报错,因为关联现在明确绑定了actor1_id和actor2_id字段。
二、获取所有合作演员
如果只需要获取某演员的所有合作演员,在Actor模型中添加合并方法去重:
def all_partners partners_as_actor1.or(partners_as_actor2).distinct end
调用示例:
actor = Actor.find(3) actor.all_partners # 返回该演员所有合作过的演员集合
三、查询合作演员及对应影片
要同时获取合作演员和对应的影片信息,添加以下方法:
def partner_with_movies ActorPartner.where("actor1_id = ? OR actor2_id = ?", id, id) .joins(:actor1, :actor2, :movie) .select(" CASE WHEN actor1_id = #{id} THEN actor2_id ELSE actor1_id END AS partner_id, CASE WHEN actor1_id = #{id} THEN actor2.name ELSE actor1.name END AS partner_name, movies.title AS movie_title, movies.id AS movie_id, actor_partners.movie_type ") .group_by { |item| [item.partner_id, item.partner_name] } end
调用示例:
actor = Actor.find(3) result = actor.partner_with_movies # 遍历输出合作演员及对应影片 result.each do |(partner_id, partner_name), movies| puts "#{partner_name} 合作影片:" movies.each do |movie| puts "- 《#{movie.movie_title}》(类型:#{movie.movie_type})" end end
四、优化建议
- 可以将
partner_with_movies的查询逻辑封装成scope,或创建数据库视图简化查询,减少重复代码。 - 可以约定
actor1_id < actor2_id来存储合作记录,避免重复数据,进一步简化查询逻辑。
内容的提问来源于stack exchange,提问作者tkhobbes
相关产品推荐
相关产品推荐

