如何避免在factory_girl中循环创建关联模型? [英] How to avoid circular creation of associated models in factory_girl?

查看:69
本文介绍了如何避免在factory_girl中循环创建关联模型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个应用,用户可以在其中使用多种服务登录,例如Google Plus,Facebook,Twitter等.

I have an app where a user can sign in with multiple services, e.g. Google Plus, Facebook, Twitter, etc.

为方便起见,我有一个has_many Identity记录的基本User模型.

To facilitate this, I have a base User model which has_many Identity records.

  • 每个Identity记录都有一个provider字段(例如"Google""Facebook"等),以指示用于登录的提供商.
  • 有一个ActiveRecord验证,仅允许用户拥有每种类型的提供程序之一.因此,用户不能有2个"Google" identities.
  • Each Identity record has a provider field (e.g. "Google", "Facebook", etc...) to indicate what provider is used to sign in.
  • There's an ActiveRecord validation that only lets a user have one of each type of provider. So a user can't have 2 "Google" identities.

我建立工厂的方式如下:

I set up my factories as follows:

FactoryGirl.define do
  factory :user do
    sequence(:name) { |n| "Julio Jones-#{n}"}
    sequence(:email) { |n| "julio.jones-#{n}@atl.com" }

    after(:create) do |user|
      create(:identity, user: user)
    end
  end

  factory :identity do
    user

    provider "Google"
    email { user.email }
    password "password"
  end
end

User模型具有创建Identity记录的回调.运行时效果很好

The User model has a callback that creates an Identity record. It works great when running

user = FactoryGirl.create(:user)

但是,如果我改为创建identity

However, if I create the identity instead

identity = FactoryGirl.create(:identity)

identity工厂将首先尝试创建父级user,该父级又将创建另一个identity.当它最终回到创建调用的identity时,已经存在另一个identity,该identity与该user相同,并且失败了.

the identity factory will first try to create a parent user, which will in turn create another identity. When it finally gets back to creating the identity I made the call to, another identity already exists with the same provider for that user and it fails.

本质上,我需要一种方法使after(:create)回调在:identity工厂正在创建user时不触发.有没有办法告诉是什么原因导致了创建特定工厂的调用?

Essentially, I need a way for the after(:create) callback to NOT trigger when the user is being created by the :identity factory. Is there a way to tell what made the call to create a particular factory?

推荐答案

我认为工厂没有一种很好的方式来告诉工厂,而无需合作即可被另一个工厂调用. (您始终可以检查caller_locations,但这并不好.)相反,让一个工厂使用瞬态属性告诉另一工厂表现不同:

I don't think there's a nice way for a factory to tell that it's been called by another without collaboration. (You can always inspect caller_locations, but that's not nice.) Instead, have one factory tell the other to behave differently using a transient attribute:

FactoryGirl.define do
  factory :user do
    transient do
      create_identity true
    end

    after(:create) do |user, evaluator|
      if evaluator.create_identity
        create(:identity, user: user)
      end
    end

  end

  factory :identity do
    association :user, factory: :user, create_identity: false
  end

end

这篇关于如何避免在factory_girl中循环创建关联模型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆