如何添加额外数据以连接 factory_bot 工厂中的表

Tho*_*mas 5 testing ruby-on-rails ruby-on-rails-5 factory-bot

我通过它们之间的关系为用户和站点提供了具有 has_many 的模型。sites_users连接表上有一个额外的数据,is_default它是布尔类型,目的是允许每个用户从该用户的相关站点列表中拥有一个默认站点。

用户模型

class User < ApplicationRecord
  has_many :sites_users
  has_many :sites, through: :sites_users
  accepts_nested_attributes_for :sites_users, allow_destroy: true
  ...
end
Run Code Online (Sandbox Code Playgroud)

用户工厂

factory :user do
  sequence(:email) { |n| "user_#{n}@example.com" }
  role { Role.find_by(title: 'Marketing') }
  image { Rack::Test::UploadedFile.new(Rails.root.join('spec', 'support', 'fixtures', 'user.jpg'), 'image/jpeg') }

  factory :super_admin do
    role { Role.find_by(title: "Super Admin") }
    admin true
  end

  before :create do |u|
    u.sites_users.build(site: site, is_default: true)
  end
Run Code Online (Sandbox Code Playgroud)

结尾

备用用户工厂方法

在用户工厂中,我也尝试了下面包含的这种方法,但找不到包含is_default: true使用此语法的方法。所以我最终放弃了这个方法,转而支持上面的before_create调用。

factory :user do
  ...
  site { site }
  ...
end
Run Code Online (Sandbox Code Playgroud)

我真的很感激任何人可以提供的任何帮助。谢谢!

架构信息

表:用户

t.string "email", default: "", null: false
t.boolean "admin", default: false
t.integer "role_id"
t.string "first_name"
t.string "last_name"
Run Code Online (Sandbox Code Playgroud)

表:站点

t.string "domain", default: "", null: false
t.string "name", default: "", null: false
t.string "logo"
t.string "logo_mark"
Run Code Online (Sandbox Code Playgroud)

表: sites_users

t.bigint "site_id", null: false
t.bigint "user_id", null: false
t.boolean "is_default", default: false
Run Code Online (Sandbox Code Playgroud)

Emm*_*elB 4

为 :site_user 创建工厂

factory :site_user, class: SiteUser do 
  site { site } # you could delete this line and add the site in factory :user
  is_default { false } # as specified in your DB
end
Run Code Online (Sandbox Code Playgroud)

site不要在工厂内创建:user,而是使用良好的语法创建其关系:

factory :user do 
  ...
  sites_users { [FactoryBot.build(:site_user, is_default: true)] }
  ...
end
Run Code Online (Sandbox Code Playgroud)

应该可以解决问题!

  • 这可行,我只需要用“site”替换“site { site }”即可。原始抛出:堆栈太深错误。谢谢你! (2认同)