Как создать фабрику для моделей, имеющих отношение has_one / own_to с проверками, которые обычно преодолеваются вложенными атрибутами? - PullRequest
3 голосов
/ 02 июня 2011

У меня есть модель Account, которая имеет модель User_one, и модель User, которая принадлежит_ модели Account.Я думаю, что основной код, необходимый для демонстрации:

class Account < ActiveRecord::Base
  has_one :user
  validates_presence_of :user
  accepts_nested_attributes_for :user
end

class User < ActiveRecord::Base
  belongs_to :account
  # validates_presence_of :account # this is not actually present,
                                   # but is implied by a not null requirement
                                   # in the database, so it only takes effect on
                                   # save or update, instead of on #valid?
end

Когда я определяю ассоциации на каждой фабрике:

Factory.define :user do |f|
  f.association :account
end

Factory.define :account do |f|
  f.association :user
end

Я получаю переполнение стека, поскольку каждый создает учетную записьпользователь рекурсивно.

Способ, который мне удалось решить, состоит в том, чтобы эмулировать вложенные формы атрибутов в моих тестах:

before :each do
  account_attributes = Factory.attributes_for :account
  account_attributes[:user_attributes] = Factory.attributes_for :user
  @account = Account.new(account_attributes)
end

Однако я бы хотел сохранить эту логикузаводской, так как он может выйти из-под контроля, как только я начну добавлять другие модули:

before :each do
  account_attributes = Factory.attributes_for :account
  account_attributes[:user_attributes] = Factory.attributes_for :user
  account_attributes[:user_attributes][:profile_attributes] = Factory.attributes_for :profile
  account_attributes[:payment_profile_attributes] = Factory.attributes_for :payment_profile
  account_attributes[:subscription_attributes] = Factory.attributes_for :subscription
  @account = Account.new(account_attributes)
end

Пожалуйста, помогите!

Ответы [ 2 ]

7 голосов
/ 11 июня 2011

Мне удалось решить эту проблему с помощью обратного вызова factory_girl after_build.

Factory.define :account do |f|
  f.after_build do |account|
    account.user ||= Factory.build(:user, :account => account)
    account.payment_profile ||= Factory.build(:payment_profile, :account => account)
    account.subscription ||= Factory.build(:subscription, :account => account)
  end
end

Factory.define :user do |f|
  f.after_build do |user|
    user.account ||= Factory.build(:account, :user => user)
    user.profile ||= Factory.build(:profile, :user => user)
  end
end

Это создаст связанные классы перед сохранением класса-владельца, поэтому проверки пройдены.

2 голосов
/ 02 июня 2011

Ознакомьтесь с документацией factory_girl .То, как вы создаете эти учетные записи, похоже, что вы на самом деле не пользуетесь factory_girl.

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

before :each do
  @account = Factory(:account, :user_id => Factory(:user).id, :profile_id => Factory(:profile).id)
end

Теперь @account будет иметь @account.user и @account.profile.Если вам нужно определить их, @profile = @account.profile прекрасно работает.

...