Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I add extra data to join table in factory_bot factories

I have models for Users and Sites with a has_many through relaitonship between them. There is one extra piece of data on the sites_users join table is_default which is type boolean with the intention being to allow each user to have one default site from the list of related sites for that user.

user model

class User < ApplicationRecord
  has_many :sites_users
  has_many :sites, through: :sites_users
  accepts_nested_attributes_for :sites_users, allow_destroy: true
  ...
end

user factory

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

end

alternate user factory Approach

On the User factory I have also tried this method included below, but cannot find a way to include the is_default: true using this syntax. So I ended up abandoning this method in favor of the above before_create call.

factory :user do
  ...
  site { site }
  ...
end

I would really appreciate any help anyone could provide. Thank you!

schema info

table: users

t.string "email", default: "", null: false
t.boolean "admin", default: false
t.integer "role_id"
t.string "first_name"
t.string "last_name"

table: sites

t.string "domain", default: "", null: false
t.string "name", default: "", null: false
t.string "logo"
t.string "logo_mark"

table: sites_users

t.bigint "site_id", null: false
t.bigint "user_id", null: false
t.boolean "is_default", default: false
like image 690
Thomas Avatar asked Oct 16 '22 13:10

Thomas


1 Answers

Create a factory for :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

Instead of creating the site within the :user factory, create its relation using the nice syntax:

factory :user do 
  ...
  sites_users { [FactoryBot.build(:site_user, is_default: true)] }
  ...
end

It should do the trick!

like image 140
EmmanuelB Avatar answered Oct 21 '22 03:10

EmmanuelB