【问题标题】:How to fix `uninitialised constant 'ActiveRecord_Relation'` in Rails 5.1.7?如何修复 Rails 5.1.7 中的“未初始化常量“ActiveRecord_Relation”?
【发布时间】:2019-04-09 09:27:48
【问题描述】:

手头的问题

我目前正在将我们的一个项目中的 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-stable 和 5.1-stable)中搜索 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

预期与实际结果

Rails 版本 5.0.7

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

Rails 版本 5.1.7

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

这两种情况之间唯一不同的是 Rails 版本。我监督了什么?感谢您的宝贵时间!

【问题讨论】:

    标签: ruby-on-rails ruby activerecord


    【解决方案1】:

    问题在于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), # ...
    

    【讨论】:

    • 谢谢!第一个选项工作得很好,但关于第二个我有一个问题:如何防止 BusinessType.all 返回一个数组而不是类本身?
    • 没关系,经过一番挖掘,我发现我可以在最后拨打.class。再次感谢您的解释!
    • 你是对的!我只是忘了在那里添加.class。感谢您的关注!我已经确定了答案。
    猜你喜欢
    • 2016-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多