Ruby Double splat(**)传参异常 Rails升级后belongs_to调用报错
Rails升级后动态调用
belongs_to的传参方案 报错核心原因
Rails 7.0版本的belongs_to方法签名为:
belongs_to(name, scope = nil, **options)
该方法仅接收2个位置参数:第一个是关联名称,第二个是关联作用域,其余所有配置参数都以关键字参数的形式收集,不再支持旧版本中把配置哈希作为第二个位置参数传入的写法。
之前尝试的几种写法错误点:
self.belongs_to relation_name, nil, options、self.belongs_to(relation_name, nil, options):把options哈希作为第三个位置参数传入,超出了方法允许的位置参数数量,直接抛出wrong number of arguments (given 3, expected 1..2)异常self.belongs_to relation_name, scope: nil, options:语法错误,普通哈希变量不能直接跟在关键字参数后传入- 旧版本写法
self.belongs_to relation_name, options:整个options哈希被识别为第二个位置参数scope,Rails会尝试将其解析为查询作用域,导致关联配置失效
正确传参方式
使用**运算符将存储配置的哈希变量解构为关键字参数传入即可。
无自定义scope的场景
显式传nil作为scope的占位参数,再传入解构后的配置:
self.belongs_to relation_name, nil, **options
有自定义scope的场景
将lambda/Proc格式的作用域作为第二个位置参数传入,再传入解构后的配置:
# 示例自定义scope:仅关联已生效的记录 assoc_scope = -> { where(status: :active) } self.belongs_to relation_name, assoc_scope, **options
等价性验证
常规静态写法:
belongs_to :User, class_name: "CompanyUser"
对应的动态调用写法:
relation_name = :User options = { class_name: "CompanyUser" } self.belongs_to relation_name, nil, **options
两种写法运行效果完全一致。
补充说明:Ruby 3.0开始正式拆分位置参数和关键字参数,哈希不会再自动隐式转换为关键字参数,这是旧代码升级后出现这类参数错误的底层原因。
内容的提问来源于stack exchange,提问作者Mr. MonoChrome
相关产品推荐
相关产品推荐

