Как исправить `неинициализированную константу 'ActiveRecord_Relation'` в Rails 5.1.7? - PullRequest
2 голосов
/ 09 апреля 2019

Проблема под рукой

В настоящее время я обновляю версию 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. Я пытался найти подкласс ActiveRecord_Relation в Google ив репозиториях Rails (5.0-stable и 5.1-stable), но я ничего не нашел, только сам класс 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.Я что-то наблюдал?Спасибо за ваше время!

1 Ответ

0 голосов
/ 09 апреля 2019

Проблема в том, что 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), # ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...