如何在Rails 5.1.7中修复`未初始化的常量'ActiveRecord_Relation'?

时间:2019-04-09 09:27:49

标签: ruby-on-rails ruby activerecord

眼前的问题

我当前正在将我们的一个项目中的Rails版本从5.0.7升级到5.1.7,但是我似乎无法找到关于为什么以前工作的调用BusinessTypes::ActiveRecord_Relation为何没有解释的原因工作了。此调用是作为规范的一部分执行的,以便检查控制器是否使用正确的参数(以及具有正确类的ActiveRecord::Relation)正确初始化了视图模型。

我尝试过的

  1. 我试图使用Rails控制台检查源代码/文件,但无济于事,因为我似乎没有找到任何源。我试过以下命令:
    • show-source BusinessTypes::ActiveRecord_Relation
    • BusinessTypes::ActiveRecord_Relation.source_location
  2. 我曾尝试在Google和Rails仓库(5.0稳定和5.1稳定)中搜索ActiveRecord_Relation子类,但没有找到任何东西,只有ActiveRecord::Relation类本身,并不能真正解决我的问题。
  3. 我也检查了变更日志,但是没有什么让我认为它对此有影响。

代码洞察力

经过测试的方法BusinessTypes#index如下:

def index
  @vm = BusinessTypes::Index.new(@business_types.all, current_user, address_confirmed: address_confirmed?)
end

错误的规格如下:

let(:user) { create(:user) }

describe 'GET #index' do
  it 'initialises the view model with the correct arguments' do
    expect(BusinessTypes::Index).to receive(:new)
      .with(kind_of(BusinessType::ActiveRecord_Relation), user, address_confirmed: true)
    get :index
  end

  context 'user has not confirmed his address' do
    let(:user) { create(:user, address_confirmed_at: nil) }

    it 'initialises the view model with the correct arguments' do
      expect(BusinessTypes::Index).to receive(:new)
        .with(kind_of(BusinessType::ActiveRecord_Relation), user, address_confirmed: false)
      get :index
    end
  end
end

预期结果与实际结果

发布版本5.0.7

该测试将通过,因为kind_of(BusinessTypes::ActiveRecord_Relation)将返回对象#<RSpec::Mocks::ArgumentMatchers::KindOf:0x00007fe52529ae20 @klass=BusinessType::ActiveRecord_Relation>,该对象与控制器作为参数传递的对象一致。

发布版本5.1.7

我收到以下错误:NameError: uninitialized constant BusinessTypes::ActiveRecord_Relation

两种情况之间唯一发生变化的是Rails版本。我监督过什么吗?谢谢您的时间!

1 个答案:

答案 0 :(得分:0)

问题在于ActiveRecord_Relation被定义为BusinessType内部的私有常量。您不能在BusinessType之外引用它。

https://www.rubydoc.info/stdlib/core/Module:private_constant

https://github.com/rails/rails/blob/f40860800c231ecd1daef6cf6b5a8a8eda76478d/activerecord/lib/active_record/relation/delegation.rb#L25

但是您可以像这样引用它:

BusinessTypes.const_get("ActiveRecord_Relation")

但是我不会以这种方式在测试中引用它。我认为更好的方法是:

expect(BusinessTypes::Index).to receive(:new).with(kind_of(BusinessType.all.class), # ...