如何使用 FactoryBot 重用类似属性的代码?
How can I reuse code for similar attributes with FactoryBot?
假设我有两个模型 Person
和 Company
,它们是不同的模型,但是它们都有一个共同的属性:address
。如果我要使用 FactoryBot,我会按如下方式实现相应的工厂:
FactoryBot.define do
factory :person do
# ...
address { Faker::Address.street_address }
end
end
FactoryBot.define do
factory :company do
# ...
address { Faker::Address.street_address }
end
end
有没有一种方法可以定义一个 address generator
我可以从工厂内的任何地方调用?。例如:
# define reusable attribute
FactoryBot.define do
attribute :address { Faker::Address.street_address }
end
FactoryBot.define do
factory :person do
# ...
generate_attribute(:address)
end
end
FactoryBot.define do
factory :company do
# ...
generate_attribute(:address)
end
end
目前我可以用 sequences
复制这种所需的行为,但它们似乎不适合这项任务。
我想你可以为一个工厂指定一个 nil class,这样你就可以为这两个工厂设置一个共同的父工厂:
factory :addressable, class: nil do
address { Faker::Address.street_address }
end
factory :person, parent: :addressable do
...
end
factory :company, parent: :addressable do
...
end
如果你想在工厂内的任何地方使用一个函数,你可以创建一个规范助手并在那里定义你的函数:
# AppSpecHelper
# spec/support/app_spec_helper
module AppSpecHelper
def generate_attribute
...
end
end
RSpec.configure do |c|
c.include AppSpecHelper
end
在rails_helper.rb
中:
RSpec.configure do |config|
config.include AppSpecHelper
end
对@Shadwell
回答的一个小补充
我相信,在较新的版本中,person
和 company
将尝试使用父级的 class 进行初始化,这将导致 Addressable.new
。这可以通过子工厂的 class
选项来避免:
# NOTE: class: nil is actually optional
factory :addressable, class: nil do
address { Faker::Address.street_address }
end
factory :person, parent: :addressable, class: 'Person' do
# ...
end
factory :company, parent: :addressable, class: 'Company' do
# ...
end
P.S。
看起来像工厂机器人 got support for several parents,所以可能会做一些关注支持
假设我有两个模型 Person
和 Company
,它们是不同的模型,但是它们都有一个共同的属性:address
。如果我要使用 FactoryBot,我会按如下方式实现相应的工厂:
FactoryBot.define do
factory :person do
# ...
address { Faker::Address.street_address }
end
end
FactoryBot.define do
factory :company do
# ...
address { Faker::Address.street_address }
end
end
有没有一种方法可以定义一个 address generator
我可以从工厂内的任何地方调用?。例如:
# define reusable attribute
FactoryBot.define do
attribute :address { Faker::Address.street_address }
end
FactoryBot.define do
factory :person do
# ...
generate_attribute(:address)
end
end
FactoryBot.define do
factory :company do
# ...
generate_attribute(:address)
end
end
目前我可以用 sequences
复制这种所需的行为,但它们似乎不适合这项任务。
我想你可以为一个工厂指定一个 nil class,这样你就可以为这两个工厂设置一个共同的父工厂:
factory :addressable, class: nil do
address { Faker::Address.street_address }
end
factory :person, parent: :addressable do
...
end
factory :company, parent: :addressable do
...
end
如果你想在工厂内的任何地方使用一个函数,你可以创建一个规范助手并在那里定义你的函数:
# AppSpecHelper
# spec/support/app_spec_helper
module AppSpecHelper
def generate_attribute
...
end
end
RSpec.configure do |c|
c.include AppSpecHelper
end
在rails_helper.rb
中:
RSpec.configure do |config|
config.include AppSpecHelper
end
对@Shadwell
回答的一个小补充我相信,在较新的版本中,person
和 company
将尝试使用父级的 class 进行初始化,这将导致 Addressable.new
。这可以通过子工厂的 class
选项来避免:
# NOTE: class: nil is actually optional
factory :addressable, class: nil do
address { Faker::Address.street_address }
end
factory :person, parent: :addressable, class: 'Person' do
# ...
end
factory :company, parent: :addressable, class: 'Company' do
# ...
end
P.S。 看起来像工厂机器人 got support for several parents,所以可能会做一些关注支持