如何添加额外数据以加入 factory_bot 工厂中的 table
How do I add extra data to join table in factory_bot factories
我有用户和网站的模型,通过它们之间的关系 has_many。 sites_users
join table 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
用户工厂
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
结束
备用用户工厂方法
在用户工厂中,我也尝试过下面包含的这种方法,但找不到使用这种语法包含 is_default: true
的方法。所以我最终放弃了这种方法,转而使用上面的 before_create
调用。
factory :user do
...
site { site }
...
end
如果有人能提供任何帮助,我将不胜感激。谢谢!
架构信息
table: 用户
t.string "email", default: "", null: false
t.boolean "admin", default: false
t.integer "role_id"
t.string "first_name"
t.string "last_name"
table: 个站点
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
因此,当我处理连接表上的额外字段时,我会创建自定义方法来构建这些连接关系,而不是尝试依赖 rails 内置方法。我已经测试了这个方法,它适用于 factory_bot 就好了。
用户模型
class User < ApplicationRecord
...
def set_site(site, default = false)
SiteUser.find_or_create_by(
user_id: id,
site_id: site.id
).update_attribute(:is_default, default)
end
end
注意:此代码是我使用的一个块,因此我可以通过相同的方法创建新的站点关系和更新默认值。如果需要,您可以将其简化为只创建而不检查是否存在。
用户工厂
factory :user do
...
# to relate to new site with default true
after(:create) do |u|
u.set_site(create(:site), true)
end
# to relate to existing site with default true
after(:create) do |u|
u.set_site(site_name, true)
end
end
如果有帮助请告诉我! (或者如果有人有更默认的 railsish 方式也能正常工作,我很想听听!)
为 :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
不是在 :user
工厂中创建 site
,而是使用漂亮的语法创建它的关系:
factory :user do
...
sites_users { [FactoryBot.build(:site_user, is_default: true)] }
...
end
它应该可以解决问题![=14=]
您可能需要考虑通过架构更改来解决此问题。您可以将 default_site_id 列添加到用户 table 并将默认站点作为用户模型的单独关联进行管理。
迁移中:
add_foreign_key :users, :sites, column: :default_site_id
在用户 class 中:
class User < ApplicationRecord
...
belongs_to :default_site, class_name: 'Site'
...
# validate that the default site has an association to this user
validate :default_site_id, inclusion: {in: sites.map(&:id)}, if: Proc.new {default_site_id.present?}
end
这将简化关联并保证任何用户都不会拥有多个 site_users 记录,其中 is_default 为真。在工厂中设置默认站点应该是微不足道的。
我有用户和网站的模型,通过它们之间的关系 has_many。 sites_users
join table 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
用户工厂
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
结束
备用用户工厂方法
在用户工厂中,我也尝试过下面包含的这种方法,但找不到使用这种语法包含 is_default: true
的方法。所以我最终放弃了这种方法,转而使用上面的 before_create
调用。
factory :user do
...
site { site }
...
end
如果有人能提供任何帮助,我将不胜感激。谢谢!
架构信息
table: 用户
t.string "email", default: "", null: false
t.boolean "admin", default: false
t.integer "role_id"
t.string "first_name"
t.string "last_name"
table: 个站点
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
因此,当我处理连接表上的额外字段时,我会创建自定义方法来构建这些连接关系,而不是尝试依赖 rails 内置方法。我已经测试了这个方法,它适用于 factory_bot 就好了。
用户模型
class User < ApplicationRecord
...
def set_site(site, default = false)
SiteUser.find_or_create_by(
user_id: id,
site_id: site.id
).update_attribute(:is_default, default)
end
end
注意:此代码是我使用的一个块,因此我可以通过相同的方法创建新的站点关系和更新默认值。如果需要,您可以将其简化为只创建而不检查是否存在。
用户工厂
factory :user do
...
# to relate to new site with default true
after(:create) do |u|
u.set_site(create(:site), true)
end
# to relate to existing site with default true
after(:create) do |u|
u.set_site(site_name, true)
end
end
如果有帮助请告诉我! (或者如果有人有更默认的 railsish 方式也能正常工作,我很想听听!)
为 :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
不是在 :user
工厂中创建 site
,而是使用漂亮的语法创建它的关系:
factory :user do
...
sites_users { [FactoryBot.build(:site_user, is_default: true)] }
...
end
它应该可以解决问题![=14=]
您可能需要考虑通过架构更改来解决此问题。您可以将 default_site_id 列添加到用户 table 并将默认站点作为用户模型的单独关联进行管理。
迁移中:
add_foreign_key :users, :sites, column: :default_site_id
在用户 class 中:
class User < ApplicationRecord
...
belongs_to :default_site, class_name: 'Site'
...
# validate that the default site has an association to this user
validate :default_site_id, inclusion: {in: sites.map(&:id)}, if: Proc.new {default_site_id.present?}
end
这将简化关联并保证任何用户都不会拥有多个 site_users 记录,其中 is_default 为真。在工厂中设置默认站点应该是微不足道的。