如何避免在factory_girl中循环创建关联模型?

2024-01-07

我有一个应用程序,用户可以使用多种服务登录,例如谷歌+、脸书、推特等

为了促进这一点,我有一个基础User模型哪个has_many Identity记录。

  • Each Identity记录有一个provider字段(例如"Google", "Facebook"等...)来指示使用哪个提供商进行登录。
  • ActiveRecord 验证只允许用户拥有每种类型的提供程序之一。所以一个用户不能有2个"Google" identities.

我的工厂设置如下:

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

The User模型有一个回调函数,它创建一个Identity记录。跑步时效果很好

user = FactoryGirl.create(:user)

但是,如果我创建identity instead

identity = FactoryGirl.create(:identity)

the identity工厂将首先尝试创建一个父工厂user,这将反过来创建另一个identity。当它最终回到创建identity我给另一个人打电话identity已经存在相同的provider为了那个原因user它失败了。

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


正如戴夫所指出的,使用瞬态属性是一种选择。另一种选择是通过nil建设相关工厂时。

FactoryGirl:避免关联之间的循环/无限循环

让我用一个例子来说明:

FactoryGirl.define do
  factory :user do
    sequence(:name) { |n| "Julio Jones-#{n}"}
    sequence(:email) { |n| "julio.jones-#{n}@atl.com" }
    # we pass user: nil here because it will cause the identity factory
    # to just skip the line user { ... }.
    identity { build(:identity, user: nil) }
  end

  factory :identity do
    # we pass user: nil here because it will cause the user factory
    # to just skip the line idenitity { ... }.
    user { build(:user, identity: nil) }
    provider "Google"
    email "[email protected] /cdn-cgi/l/email-protection"
    password "password"
  end
end 

当我们打电话时build(:user),代码最终到达以下行:

identity { build(:identity, user: nil) }

这称为身份工厂。当它到达通常会构建用户关联的行时(user { build(:user, identity: nil) }),它会跳过它,因为 user 已被设置(为零)。恭喜,您刚刚避免了循环依赖!

当你打电话时它的工作方式是一样的build(:identity).


FactoryGirl:从关联工厂中的一个工厂访问属性

最后一件事:在您的情况下,您需要访问身份工厂中用户的电子邮件属性。在您的代码示例中,您说:

factory :identity do
  ...
  email { user.email }
end

显然,当我们调用时会失败build(:user)因为当我们调用身份工厂时,我们将 user 设置为 nil。不要害怕!当我们调用身份工厂时,我们只需传递一个新的用户对象和电子邮件即可。所以该行变为:

identity { build(:identity, user: User.new(email: email)) }

这既可以防止循环、无限的关联循环,也可以确保电子邮件属性在身份工厂中可用。

最后,您的代码将如下所示:

FactoryGirl.define do
  factory :user do
    sequence(:name) { |n| "Julio Jones-#{n}"}
    sequence(:email) { |n| "julio.jones-#{n}@atl.com" }
    # we pass user: User.new here because it will...
    # a) cause the identity factory to skip the line user { ... } and
    # b) allow us to use the email attribute in the identity factory.
    identity { build(:identity, user: User.new(email: email)) }
  end

  factory :identity do
    # we pass user: nil here because it will cause the user factory
    # to just skip the line idenitity { ... }.
    user { build(:user, identity: nil) }
    provider "Google"
    email { user.email }
    password "password"
  end
end 

希望它有帮助!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何避免在factory_girl中循环创建关联模型? 的相关文章

随机推荐

  • 无法打开主机 WCF REST 服务

    我正在尝试实现一些 WCF 和 REST 服务来在我的服务器上上传文件 并且我找到了一些我正在尝试实现的代码 但尚未成功 My code class Program static void Main string args string a
  • 如何设置 Dojo 对话框打开的位置?

    我有一个 Dojo 对话框 当用户单击页面上的元素时会打开该对话框 我想控制它打开的位置 我真的希望它在单击的其他 dom 元素旁边 相对于 打开 但我似乎可以弄清楚如何执行上述任一操作 感谢您的任何建议 打开一个与 dojo 相对于单击位
  • 引入预检 CORS 请求背后的动机是什么?

    跨域资源共享是一种允许网页向另一个域 从维基百科 https en wikipedia org wiki Cross origin resource sharing 过去几天我一直在摆弄 CORS 我想我对一切的工作原理有了很好的理解 所以
  • 在浏览器中播放 HTML5 视频 - 什么适用于大多数 Android 设备?

    我正在尝试让 HTML5 视频在移动设备上播放 它们似乎在最新版本的 iOS 上运行良好 但在 Android 设备上却出现了很多不一致的情况 我正在使用 video js 并监听缩略图上的点击 这反过来会用 HTML5 视频替换该元素并自
  • 当每个字符位于一个 div 中时,如何分别对它们应用样式?

    我想为我的一个 div 的每个字母提供不同的背景 CSS 样式 例如 div class hello 1999 div 所以每个词背后都有一个类似计数器的背景 以供参考 如何在不将 div 类一一分离的情况下做到这一点 如果您想在页面加载后
  • 关于重定向的 Google 脚本无法正常工作并出现特殊错误,发生了什么

    相同的代码 从未修改过 然而 自 9 月份以来 javascript top location href https and window open https top 以上所有内容都停止工作并且出现错误 尝试导航顶级窗口的框架使用 允许用
  • 最新 PlayServices 8.3 中的 GoogleSignInAccount 内部崩溃

    Play 服务的最新版本 8 3 存在与 GoogleSignInAccount 相关的问题 我们收到了由此产生的崩溃 这是堆栈跟踪 Android 4 4 4 Manufacturer Sony Model D5503 Date Thu
  • C 中的递归。将非递归函数变成递归函数

    gcd 应该是一个递归函数 它应该返回 void 它应该采用两个正整数并将 GCD 放在第三个参数中 这是我编码的 gcd 函数 然而 我意识到这不是一个递归函数 我如何更改此代码 使其成为递归函数 void gcd int x int y
  • 如何使用 Access VBA 在 textBox.Setfocus 之后选择 TextBox 中的所有文本

    当我单击 或双击 Access 表单的文本框中时 我需要选择其中的所有文本 我尝试了以下代码 但没有成功 Me txt CompraPreco SelStart 0 Me txt CompraPreco SelLength Len Me t
  • Java 双重比较 epsilon

    我编写了一个类 用 Java 中的两个双精度数来测试相等 小于和大于 我的一般情况是比较价格 精确度可以达到半美分 59 005 与 59 395 相比 我选择的 epsilon 适合这些情况吗 private final static d
  • 向面板添加垂直滚动条

    我正在尝试做一个Panel可滚动 但只能垂直滚动 所以AutoScroll不起作用 因为子控件必须越过左边缘 那么这是如何做到的呢 尝试 仅 垂直滚动 自动滚动需要为 false 才能接受更改 mypanel AutoScroll fals
  • 在 R 中设置 kmeans 的静态中心

    我想根据预先确定的中心点 my center Points 对长和纬度 my long lats 列表进行分组 当我跑步时 k lt kmeans as matrix my long lats centers as matrix my ce
  • 使用 UIPasteBoard 复制图像 (Swift)

    我最近看到这个项目 用户可以从自定义键盘上点击 GIF 他们会看到一个 复制的 工具栏出现 我有一个问题 如何在产品中重现此工具提示GIF 教程 http o aolcdn com hss storage midas 27c2fb5dfec
  • jQuery 灯箱画廊

    是否存在具有标准灯箱功能的 jQuery 插件 在 灯箱 窗口中 我想在同一 灯箱 窗口中的某处 左侧 底部等 将当前图像和其余图 像显示为缩略图 ColorBox http colorpowered com colorbox 一个轻量级
  • 对 Automapper 配置文件进行单元测试

    我的确想要测试自定义逻辑CreateMap方法 我愿意NOT想要测试某些类型的映射是否存在 我该怎么做或者我需要知道哪些课程 我很感激该文件的每一个提示 Automapper 单元测试似乎很少见 public class UnitProfi
  • 计算 numpy.chararray 中字符出现次数的最快方法

    Python主义者 计算字符在字符中出现的最快方法是什么numpy character array 我正在做以下事情 In 59 for i in range 10 m input Enter A or B rr 0 i m Enter A
  • 使用 ASP MVC 下载并显示私有 Azure Blob

    我将 ASP MVC 5 Razor 与 Microsoft Azure Blob 存储结合使用 我可以使用 MVC 成功地将文档和图像上传到 Blob 存储 但我很难找到一些如何下载和显示文件的 MVC 示例 如果 blob 存储为公共文
  • ConstraintLayout 不会省略 TextView 中的长文本

    我有一个TextView在图像的右侧 我试图在图像旁边放置一些长文本 但该文本应通过在末尾添加 自动结束 然而 这是行不通的 我使用这个布局
  • Google 地图 API - geocode() 不返回纬度和经度

    我试图使用以下代码通过地址获取纬度和经度 function initialize directionsDisplay new google maps DirectionsRenderer geocoder new google maps G
  • 如何避免在factory_girl中循环创建关联模型?

    我有一个应用程序 用户可以使用多种服务登录 例如谷歌 脸书 推特等 为了促进这一点 我有一个基础User模型哪个has many Identity记录 Each Identity记录有一个provider字段 例如 Google Faceb