Rails 5中belongs_to关联如何忽略ID,通过唯一名称建立关联?
在Rails 5中用字符串name字段建立关联的实现方案
这场景我熟,Rails其实原生就支持打破默认的id主键关联,不用搞复杂的hack,直接用关联的内置选项就能搞定,而且是最简洁的方式。
正确的关联写法
首先你原来的belongs_to定义里那个scope是错的——lambda里直接写nesti_commodity会报未定义变量的错误,而且这也不是正确的关联匹配方式。正确的做法是明确指定foreign_key和primary_key:
1. 修正CommodityToProducts模型的关联
# app/models/commodity_to_product.rb class CommodityToProduct < ApplicationRecord belongs_to :nesti_commodity, class_name: "NestiCommodity", foreign_key: :nesti_commodity, # 当前模型用来存关联字符串的字段 primary_key: :name, # NestiCommodity模型用来匹配的字段(name字符串) inverse_of: :commodity_to_products end
2. 对应更新NestiCommodity的has_many关联
为了让双向关联正常工作,也要在NestiCommodity里同步指定这两个选项:
# app/models/nesti_commodity.rb class NestiCommodity < ApplicationRecord has_many :commodity_to_products, foreign_key: :nesti_commodity, primary_key: :name, inverse_of: :nesti_commodity end
为什么这样可行?
Rails默认的关联逻辑是:用当前模型的xxx_id字段,匹配关联模型的id主键。我们通过foreign_key告诉Rails“别找xxx_id了,用我指定的这个字符串字段”,再用primary_key告诉它“别匹配对方的id了,匹配对方的name字段”。这样框架在加载关联时,会自动生成WHERE nesti_commodities.name = ?的查询,完全符合你的需求。
最简洁的打破约定方式
就是直接利用Rails关联的foreign_key和primary_key选项——这是框架原生支持的扩展方式,不需要额外引入gem,也不用自己写自定义查询或回调,代码简洁且符合Rails的设计思路。
重要注意事项
一定要确保NestiCommodity的name字段是唯一的!因为belongs_to关联期望只能找到一个匹配的记录,如果name重复,会导致关联加载报错。所以记得给name字段加唯一索引:
# 生成迁移文件后修改内容 class AddUniqueIndexToNestiCommoditiesName < ActiveRecord::Migration[5.2] def change add_index :nesti_commodities, :name, unique: true end end
内容的提问来源于stack exchange,提问作者ruby_object
相关产品推荐
相关产品推荐

