У меня есть фабрика, которая генерирует разработанного пользователя с ролями в движке.Модель User has_many :roles through: :roles_users
.Я могу заставить код работать с предложением after(:create)
, но не с ключевым словом association:
.
Это работает:
app / model / myengine / role.rb
module MyEngine
class User < ActiveRecord::Base
has_many :roles_users
has_many :roles, through: :roles_users
end
end
spec / factories / role.rb
factory :role, class: "MyEngine::Role" do
type: { 'admin' }
end
factory :user, class: "MyEngine::User" do
sequence(:email) { |n| "tester_#{n}@example.com" }
password { 'xxx' }
password_confirmation { 'xxx' }
after(:create) do |user|
user.roles << FactoryBot.create(:role)
end
end
Но это не , и тест завершается с undefined method 'each' for #<MyEngine::Role:0x0...>
при инициализации:
factory :user, class: "MyEngine::User" do
sequence(:email) { |n| "tester_#{n}@example.com" }
password { 'xxx'}
password_confirmation { 'xxx' }
association: :roles, factory: :role
end
Обновлено / отредактировано ниже:
Документ FactoryBot предлагает только возможность после (: create) ловушки по определенной причине.Из комментариев пользователей есть две проблемы с вышеуказанным кодом:
- не использует коллекцию
- объект не существует, когда присоединяется ассоциация
Используя предложение @Vasfed, ассоциация ролей может быть назначена непосредственно с использованием коллекции вместо объекта:
factory :user, class: "MyEngine::User" do
sequence(:email) { |n| "tester_#{n}@example.com" }
password { 'xxx'}
password_confirmation { 'xxx' }
roles { [ create(:role) ] }
end
Согласно предложению @ulferts использовать new вместо create:
factory :user, class: "MyEngine::User" do
sequence(:email) { |n| "tester_#{n}@example.com" }
password { 'xxx'}
password_confirmation { 'xxx' }
roles { [ build(:role) ] }
end
Оба будут выдавать:
ActiveRecord::RecordInvalid: Validation failed: Roles users is invalid
Поскольку модель не имеет проверки, это может указывать на проблему с отсутствующей записью в таблице FK или на невозможность найти таблицу FK, вероятно, из-за разрешения пространства имен.