Ruby 2.4升级至2.7后rspec报BigDecimal无new方法,如何定位出错gem
问题根因
undefined method 'new' for BigDecimal:Class 错误是Ruby 2.7版本变更导致的:Ruby 2.7开始标准库自带的BigDecimal移除了旧的BigDecimal.new构造方法,改为直接调用BigDecimal()创建实例。你的主应用代码没有调用这个旧API,且生产环境不加载test分组的gem,所以应用本身可以正常启动,只有加载了测试专属gem的rspec执行时会报错。
定位问题gem的操作步骤
你可以通过临时加调试代码,打印Bundler加载gem的顺序,精准定位是哪个gem调用了旧的BigDecimal API:
- 替换
config/application.rb中第17行的Bundler.require(*Rails.groups)代码,替换为以下调试代码:
Rails.groups.each do |group| Bundler.environment.dependencies_for(:default, group).each do |dep| puts "正在加载gem: #{dep.name}" require dep.name rescue NoMethodError => e if e.message.include?('BigDecimal') puts "!!! 触发报错的gem是:#{dep.name}" raise e end end end
- 重新执行
rspec,看控制台最后打印的gem名称,就是触发问题的依赖。
针对性解决方案
从你贴的报错日志和Gemfile配置来看,大概率是老版本的shoulda-matchers导致的问题:你当前用的是未正式发布的rails-5分支开发版,这个分支版本没有做Ruby 2.7兼容,日志里也已经出现了该gem的常量重复定义警告。你可以按优先级尝试以下修复方案:
- 替换
shoulda-matchers为正式兼容版本:
将Gemfile中shoulda-matchers的配置改为:gem 'shoulda-matchers', '~> 4.0' - 若修改后仍报错,给测试组的其他无版本约束的gem指定兼容Ruby 2.7的版本:
rspec-rails指定到~> 4.0及以上database_cleaner指定到~> 1.8及以上
- 以上修改都不生效的话,可在Gemfile中强制引入兼容版本的bigdecimal,向下兼容旧API调用:
gem 'bigdecimal', '~> 2.0' - 修改完成后执行
bundle update shoulda-matchers rspec-rails bigdecimal更新对应依赖即可。
内容的提问来源于stack exchange,提问作者Chloe
相关产品推荐
相关产品推荐

