Странный ActiveRecord :: соответствие типов ассоциаций

#ruby-on-rails #ruby

#ruby-on-rails #ruby

Вопрос:

Я получаю очень странную ошибку при запуске спецификации:

 Failure/Error: entity = Factory.create(:entity, :name => "Test Entity", :creator => user)
 ActiveRecord::AssociationTypeMismatch:
   ::User(#97318850) expected, got User(#92770800)
  

Это код, который приводит к вышеупомянутой ошибке. Фабрика — это фабрика factory_girl.

   user = Factory(:user, :username => "kai", :email => "xxx@yyy.com", :password => "testing")
  entity = Factory.create(:entity, :name => "Test Entity", :creator => user)
  

Когда я использую :creator => User.first , все работает так, как ожидалось. Я распечатал User.first и user , но не вижу разницы.

Любые предложения, что, черт возьми, здесь не так?

Обновить

Я также получил эту ошибку при запуске этой простой спецификации запроса

 describe "Entities" do
  it "should succeed" do
    entity = Factory.create(:entity, :name => "Test Entity 1")
    visit root_path
  end

  it "should also succeed" do
    entity = Factory.create(:entity, :name => "Test Entity 2")
    property = Factory.create(:property, :entity => entity)
  end
end
  

На этот раз я получаю

 Failure/Error: property = Factory.create(:property, :entity => entity)
 ActiveRecord::AssociationTypeMismatch:
   Entity(#103620190) expected, got Entity(#96047070)
  

когда я удаляю visit root_path , все работает нормально (также при запуске каждой спецификации отдельно). Это просто кажется проблемой для спецификаций запроса. Другие спецификации (модель, контроллер), похоже, работают нормально. Я использую Capybara 1.0.0.beta1 и RSpec 2.5.

Что означает это число за именем класса?

Ответ №1:

Это ошибка, которая возникает при загрузке двух разных версий модели. Раньше я пользовался этим в более старой версии Rails 3, поскольку в среде разработки был небольшой сбой с перезагрузкой модели. Цифры после имени класса относятся к разным версиям класса.

Само собой разумеется, что такого рода ошибки могут возникать в режиме разработки, но этого не должно быть в тестовом режиме, поскольку по умолчанию классы кэшируются. Посмотрите config/environments/test.rb файл, чтобы убедиться, что для этого cache_classes установлено значение true.

Также убедитесь, что вы используете последнюю версию Rails, 3.0.7. Возможно, это ошибка, которая с тех пор была исправлена. Пока мы этим занимаемся, убедитесь, что вы находитесь на factory_girl 1.3.3. При абсолютно правильном использовании API, что, я думаю, вы делаете, остаются единственные возможности, что что-то неправильно настроено или что это ошибка в чужом коде.

Комментарии:

1. Действительно, я cache_classes установил значение false (причина некоторых старых проблем со spork … что в то же время, похоже, больше не вызывает проблем). Теперь все работает нормально. Большое спасибо за вашу помощь.

2. 1 — Спасибо! Мне это тоже помогло! Задавался вопросом, что, черт возьми, это было!

3. Я также иногда вижу это, когда запускаю spork с cache_classes, установленным в false, чтобы я мог быстро запускать rspec… Я не нашел способа обойти это, кроме запуска спецификаций без spork.

4. Работа с базовым приложением во внешнем интерфейсе (и никогда не перезапускающим сервер) В итоге я столкнулся с этой ошибкой, также решаемой с перезапуском сервера, спасибо!

5. У меня была такая же проблема в консоли после использования reload! . Выход и запуск консоли решили проблему. Поэтому reload! также возникают некоторые проблемы с кэшированием классов. (С использованием rails 4)

Ответ №2:

Вместо того, чтобы отключать кэширование классов, что может усугублять ситуацию во время разработки, проблема может исчезнуть, если вы обновите свой объект перед его использованием. В моем случае я загружал объект из ассоциации:

 desired_object = foo.bar
  

Поиск элемента вместо этого устранил проблему и не требовал кэширования классов.

 desired_object = Bar.find(foo.bar_id)
  

Я знаю, что это не идеально, но, возможно, это поможет кому-то выяснить, почему это вообще происходит.

Комментарии:

1. Я взломал это, вызвав .reload объект после ассоциации, как в foo.bar.reload

Ответ №3:

Для комбинации Rails Spring factory_girl это исправлено начиная с версии v4.4.1 factory_girl_rails (февраль 2014) см.https://github.com/thoughtbot/factory_girl_rails/pull/121

Ответ №4:

Подобная ошибка может возникнуть, если вы используете Spring или любой другой предварительный загрузчик приложения на Rails, обязательно перезапустите его.

 spring stop
spring start
# or usually bin/rails s or bin/rails c for console
  

Ответ №5:

Проблема для меня заключалась в определении моей фабрики, где я использовал дополнительные фабрики для заполнения полей идентификатора. Я случайно сослался на атрибут, которого не существовало в таблице (account вместо account_id). Смотрите пример ниже.

 factory Omni::CustomerAccount do
  sequence(:display_name) {|n| "test #{n}"}
  customer_id :customer  # this is correct
  account :account  # wrong - this should say account_id :account
end
  

Надеюсь, это кому-то поможет.