You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ruby 3.x迁移时RSpec测试中Proc代码行出现参数错误

迁移Ruby 2.7到3.0.4时ActiveRecord关联报错排查

问题背景

正在将基于Ruby 2.7的应用迁移至Ruby 3.0.4,应用使用Rails 6.1.7与rspec 5.1.2。其中CommonIssue模型与Issue模型存在has_many关联,执行测试代码时触发参数错误。

报错信息

#<ArgumentError: wrong number of arguments (given 2, expected 0..1)>

触发代码

两种写法均会触发相同错误:
写法1:

proc { CommonIssue.first.issues << Issue.first }
  .should raise_error("Validation failed: Issue has already been taken")

写法2:

expect { CommonIssue.first.issues << Issue.first }
  .to raise_error("Validation failed: Issue has already been taken")

堆栈跟踪

Failure/Error:
   proc { CommonIssue.first.issues << Issue.first }
     .should raise_error("Validation failed: Issue has already been taken")
 
   期望捕获异常"Validation failed: Issue has already been taken",实际得到#<ArgumentError: wrong number of arguments (given 2, expected 0..1)>,调用栈如下:
     # /usr/local/bundle/gems/i18n-1.12.0/lib/i18n.rb:210:in `translate'
     # ./config/initializers/dynamic_form_monkey_patch.rb:55:in `block (2 levels) in full_messages'
     # ./config/initializers/dynamic_form_monkey_patch.rb:47:in `each'
     # ./config/initializers/dynamic_form_monkey_patch.rb:47:in `block in full_messages'
     # /usr/local/bundle/gems/activemodel-6.1.7/lib/active_model/errors.rb:237:in `each'
     # /usr/local/bundle/gems/activemodel-6.1.7/lib/active_model/errors.rb:237:in `each'
     # ./config/initializers/dynamic_form_monkey_patch.rb:34:in `full_messages'
     # /usr/local/bundle/gems/activerecord-6.1.7/lib/active_record/validations.rb:21:in `initialize'
     # /usr/local/bundle/gems/activerecord-6.1.7/lib/active_record/validations.rb:80:in `new'
     # /usr/local/bundle/gems/activerecord-6.1.7/lib/active_record/validations.rb:80:in `raise_validation_error'
     # /usr/local/bundle/gems/activerecord-6.1.7/lib/active_record/validations.rb:53:in `save!'
     # /usr/local/bundle/gems/activerecord-6.1.7/lib/active_record/transactions.rb:302:in `block in save!'
     # /usr/local/bundle/gems/activerecord-6.1.7/lib/active_record/transactions.rb:354:in `block in with_transaction_returning_status'
     # /usr/local/bundle/gems/activerecord-6.1.7/lib/active_record/connection_adapters/abstract/database_statements.rb:318:in `transaction'
     # /usr/local/bundle/gems/activerecord-6.1.7/lib/active_record/transactions.rb:350:in `with_transaction_returning_status'
     # /usr/local/bundle/gems/activerecord-6.1.7/lib/active_record/transactions.rb:302:in `save!'
     # /usr/local/bundle/gems/activerecord-6.1.7/lib/active_record/suppressor.rb:48:in `save!'
     # /usr/local/bundle/gems/activerecord-6.1.7/lib/active_record/associations/has_many_through_association.rb:80:in `save_through_record'
     # /usr/local/bundle/gems/activerecord-6.1.7/lib/active_record/associations/has_many_through_association.rb:31:in `insert_record'
     # /usr/local/bundle/gems/activerecord-6.1.7/lib/active_record/associations/collection_association.rb:437:in `block (2 levels) in concat_records'
     # /usr/local/bundle/gems/activerecord-6.1.7/lib/active_record/associations/collection_association.rb:462:in `replace_on_target'
     # /usr/local/bundle/gems/activerecord-6.1.7/lib/active_record/associations/collection_association.rb:283:in `add_to_target'
     # /usr/local/bundle/gems/activerecord-6.1.7/lib/active_record/associations/collection_association.rb:435:in `block in concat_records'
     # /usr/local/bundle/gems/activerecord-6.1.7/lib/active_record/associations/collection_association.rb:433:in `each'
     # /usr/local/bundle/gems/activerecord-6.1.7/lib/active_record/associations/collection_association.rb:433:in `concat_records'
     # /usr/local/bundle/gems/activerecord-6.1.7/lib/active_record/associations/has_many_association.rb:130:in `concat_records'
     # /usr/local/bundle/gems/activerecord-6.1.7/lib/active_record/associations/has_many_through_association.rb:40:in `concat_records'
     # /usr/local/bundle/gems/activerecord-6.1.7/lib/active_record/associations/collection_association.rb:121:in `block in concat'
     # /usr/local/bundle/gems/activerecord-6.1.7/lib/active_record/associations/collection_association.rb:136:in `block in transaction'
     # /usr/local/bundle/gems/activerecord-6.1.7/lib/active_record/connection_adapters/abstract/database_statements.rb:320:in `block in transaction'
     # /usr/local/bundle/gems/activerecord-6.1.7/lib/active_record/connection_adapters/abstract/transaction.rb:319:in `block in within_new_transaction'
     # /usr/local/bundle/gems/activesupport-6.1.7/lib/active_support/concurrency/load_interlock_aware_monitor.rb:26:in `block (2 levels) in synchronize'
     # /usr/local/bundle/gems/activesupport-6.1.7/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `handle_interrupt'
     # /usr/local/bundle/gems/activesupport-6.1.7/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `block in synchronize'
     # /usr/local/bundle/gems/activesupport-6.1.7/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `handle_interrupt'
     # /usr/local/bundle/gems/activesupport-6.1.7/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `synchronize'
     # /usr/local/bundle/gems/activerecord-6.1.7/lib/active_record/connection_adapters/abstract/transaction.rb:317:in `within_new_transaction'
     # /usr/local/bundle/gems/activerecord-6.1.7/lib/active_record/connection_adapters/abstract/database_statements.rb:320:in `transaction'
     # /usr/local/bundle/gems/activerecord-6.1.7/lib/active_record/transactions.rb:209:in `transaction'
     # /usr/local/bundle/gems/activerecord-6.1.7/lib/active_record/associations/collection_association.rb:135:in `transaction'
     # /usr/local/bundle/gems/activerecord-6.1.7/lib/active_record/associations/collection_association.rb:121:in `concat'
     # /usr/local/bundle/gems/activerecord-6.1.7/lib/active_record/associations/has_many_through_association.rb:21:in `concat'
     # /usr/local/bundle/gems/activerecord-6.1.7/lib/active_record/associations/collection_proxy.rb:1027:in `<<'
     # ./spec/models/common_issue_spec.rb:46:in `block (3 levels) in <top (required)>'
     # ./spec/models/common_issue_spec.rb:46:in `block (2 levels) in <top (required)>'
     # ./spec/spec_helper.rb:76:in `block (3 levels) in <top (required)>'
     # /usr/local/bundle/gems/database_cleaner-core-2.0.1/lib/database_cleaner/strategy.rb:30:in `cleaning'
     # /usr/local/bundle/gems/database_cleaner-core-2.0.1/lib/database_cleaner/cleaners.rb:34:in `block (2 levels) in cleaning'
     # /usr/local/bundle/gems/database_cleaner-core-2.0.1/lib/database_cleaner/cleaners.rb:35:in `cleaning'
     # ./spec/spec_helper.rb:75:in `block (2 levels) in <top (required)>'
     # /usr/local/bundle/gems/webmock-3.18.1/lib/webmock/rspec.rb:37:in `block (2 levels) in <top (required)>'
 # ./spec/models/common_issue_spec.rb:46:in `block (2 levels) in <top (required)>'
 # ./spec/spec_helper.rb:76:in `block (3 levels) in <top (required)>'
 # /usr/local/bundle/gems/database_cleaner-core-2.0.1/lib/database_cleaner/strategy.rb:30:in `cleaning'
 # /usr/local/bundle/gems/database_cleaner-core-2.0.1/lib/database_cleaner/cleaners.rb:34:in `block (2 levels) in cleaning'
 # /usr/local/bundle/gems/database_cleaner-core-2.0.1/lib/database_cleaner/cleaners.rb:35:in `cleaning'
 # ./spec/spec_helper.rb:75:in `block (2 levels) in <top (required)>'
 # /usr/local/bundle/gems/webmock-3.18.1/lib/webmock/rspec.rb:37:in `block (2 levels) in <top (required)>'

问题原因

从堆栈跟踪可以看到,错误根源在./config/initializers/dynamic_form_monkey_patch.rb第55行调用I18n.translate时传入了2个参数,但当前使用的i18n 1.12.0版本的translate方法只接受0到1个参数(Ruby 3.0对参数传递的兼容性更严格,加上i18n版本的API变化)。

这个monkey patch是针对旧版本Ruby/Rails/i18n编写的,迁移到Ruby 3.0后,参数传递方式不再兼容,导致抛出参数数量错误。

修复方案

  1. 打开config/initializers/dynamic_form_monkey_patch.rb文件,定位到第55行的I18n.translate调用。
  2. 修改参数传递方式,符合i18n 1.12.0的API要求:
    • 如果原来的调用是I18n.translate(key, some_value),需要改为使用关键字参数,比如I18n.translate(key, default: some_value)或者其他对应的关键字参数,具体取决于代码的业务逻辑。
  3. 保存修改后重新运行测试,验证错误是否消失。

内容的提问来源于stack exchange,提问作者Chris Root

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 20:57:08