Rails自定义外键关联问题:让Member关联Membership的rank主键
解决Rails自定义主键关联问题
问题根源
members表通过t.references生成的membership_id是整数类型,但memberships的主键rank是字符串类型,类型不匹配导致关联失败Membership模型未明确指定自定义主键,Rails默认仍会查找id列,触发PG::UndefinedColumn错误Member模型的关联未指定正确的外键和主键,导致创建记录时出现membership_id = 0的异常
修改步骤
1. 修正数据库结构(schema.rb)
把members表的关联字段改为字符串类型,并手动添加外键约束:
create_table 'memberships', id: false, primary_key: :rank, force: :cascade do |t| t.string 'rank' t.integer 'discount_rate' t.datetime 'created_at', precision: 6, null: false t.datetime 'updated_at', precision: 6, null: false end create_table 'members', force: :cascade do |t| # 替换原来的t.references,用字符串类型存储rank t.string 'membership_rank', index: true t.string 'name' t.datetime 'created_at', precision: 6, null: false t.datetime 'updated_at', precision: 6, null: false end # 手动添加外键,指定关联的外键列和主键列 add_foreign_key 'members', 'memberships', column: 'membership_rank', primary_key: 'rank', on_delete: :cascade
2. 修正Membership模型
明确指定自定义主键,并配置正确的关联:
class Membership < ApplicationRecord # 告诉Rails用rank作为主键 self.primary_key = 'rank' has_many :members, foreign_key: :membership_rank, dependent: :destroy validates :rank, uniqueness: true end
3. 修正Member模型
指定关联的外键和对应主键:
class Member < ApplicationRecord belongs_to :membership, foreign_key: :membership_rank, primary_key: :rank validates :name, length: { maximum: 30 }, uniqueness: true, presence: true end
验证修改
在rails c中测试:
# 创建会员等级 vip = Membership.create(rank: 'VIP', discount_rate: 20) # 创建关联的会员 Member.create(name: '张三', membership: vip) # 查看关联是否生效 Member.last.membership.rank # 应该返回'VIP'
内容的提问来源于stack exchange,提问作者ddzxc
相关产品推荐
相关产品推荐

