Allow inline sequences in traits to have same name
Fixes #1257 When sequence rewinding was first introduced in #1078 it only applied to globally defined sequences. To get rewinding to work for inline sequences as well we registered them "privately" in the global registry in #1164. Unfortunately in #1164 we did not take inline sequences inside traits into consideration. Since trait names are not unique, it is possibly to get a `FactoryBot::DuplicateDefinitionError` when defining two sequences that have the same name in two traits that have the same name. This PR abandons the idea of "privately" registering inline sequences, and instead keeps a separate list of all the inline sequences just for the purpose of rewinding them.
This commit is contained in:
parent
d2a30d6fd2
commit
79331a3863
|
@ -115,6 +115,7 @@ module FactoryBot
|
||||||
|
|
||||||
def self.rewind_sequences
|
def self.rewind_sequences
|
||||||
sequences.each(&:rewind)
|
sequences.each(&:rewind)
|
||||||
|
Internal.rewind_inline_sequences
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.register_trait(trait)
|
def self.register_trait(trait)
|
||||||
|
|
|
@ -1,7 +1,14 @@
|
||||||
module FactoryBot
|
module FactoryBot
|
||||||
# @api private
|
# @api private
|
||||||
class Configuration
|
class Configuration
|
||||||
attr_reader :factories, :sequences, :traits, :strategies, :callback_names
|
attr_reader(
|
||||||
|
:callback_names,
|
||||||
|
:factories,
|
||||||
|
:inline_sequences,
|
||||||
|
:sequences,
|
||||||
|
:strategies,
|
||||||
|
:traits,
|
||||||
|
)
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
@factories = Decorator::DisallowsDuplicatesRegistry.new(Registry.new("Factory"))
|
@factories = Decorator::DisallowsDuplicatesRegistry.new(Registry.new("Factory"))
|
||||||
|
@ -10,6 +17,7 @@ module FactoryBot
|
||||||
@strategies = Registry.new("Strategy")
|
@strategies = Registry.new("Strategy")
|
||||||
@callback_names = Set.new
|
@callback_names = Set.new
|
||||||
@definition = Definition.new(:configuration)
|
@definition = Definition.new(:configuration)
|
||||||
|
@inline_sequences = []
|
||||||
|
|
||||||
to_create(&:save!)
|
to_create(&:save!)
|
||||||
initialize_with { new }
|
initialize_with { new }
|
||||||
|
|
|
@ -117,9 +117,8 @@ module FactoryBot
|
||||||
#
|
#
|
||||||
# Except that no globally available sequence will be defined.
|
# Except that no globally available sequence will be defined.
|
||||||
def sequence(name, *args, &block)
|
def sequence(name, *args, &block)
|
||||||
sequence_name = "__#{@definition.name}_#{name}__"
|
sequence = Sequence.new(name, *args, &block)
|
||||||
sequence = Sequence.new(sequence_name, *args, &block)
|
FactoryBot::Internal.register_inline_sequence(sequence)
|
||||||
FactoryBot.register_sequence(sequence)
|
|
||||||
add_attribute(name) { increment_sequence(sequence) }
|
add_attribute(name) { increment_sequence(sequence) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@ module FactoryBot
|
||||||
# @api private
|
# @api private
|
||||||
module Internal
|
module Internal
|
||||||
class << self
|
class << self
|
||||||
|
delegate :inline_sequences, to: :configuration
|
||||||
|
|
||||||
def configuration
|
def configuration
|
||||||
@configuration ||= Configuration.new
|
@configuration ||= Configuration.new
|
||||||
end
|
end
|
||||||
|
@ -9,6 +11,14 @@ module FactoryBot
|
||||||
def reset_configuration
|
def reset_configuration
|
||||||
@configuration = nil
|
@configuration = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def register_inline_sequence(sequence)
|
||||||
|
inline_sequences.push(sequence)
|
||||||
|
end
|
||||||
|
|
||||||
|
def rewind_inline_sequences
|
||||||
|
inline_sequences.each(&:rewind)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -90,4 +90,34 @@ describe "FactoryBot.rewind_sequences" do
|
||||||
expect(user.email).to eq "local-somebody1@example.com"
|
expect(user.email).to eq "local-somebody1@example.com"
|
||||||
expect(email).to eq "global-somebody1@example.com"
|
expect(email).to eq "global-somebody1@example.com"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "allows setting sequences within identically named traits" do
|
||||||
|
define_class("User") { attr_accessor :email }
|
||||||
|
define_class("Person") { attr_accessor :email }
|
||||||
|
|
||||||
|
FactoryBot.define do
|
||||||
|
factory :user do
|
||||||
|
trait :with_email do
|
||||||
|
sequence(:email) { |n| "user#{n}@example.com" }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
factory :person do
|
||||||
|
trait :with_email do
|
||||||
|
sequence(:email) { |n| "person#{n}@example.com" }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
build_list(:user, 2, :with_email)
|
||||||
|
build_list(:person, 2, :with_email)
|
||||||
|
|
||||||
|
FactoryBot.rewind_sequences
|
||||||
|
|
||||||
|
user = build(:user, :with_email)
|
||||||
|
person = build(:person, :with_email)
|
||||||
|
|
||||||
|
expect(user.email).to eq "user1@example.com"
|
||||||
|
expect(person.email).to eq "person1@example.com"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -106,18 +106,20 @@ describe FactoryBot::DefinitionProxy, "#sequence" do
|
||||||
|
|
||||||
it "creates a new sequence starting at 1" do
|
it "creates a new sequence starting at 1" do
|
||||||
proxy = build_proxy(:factory)
|
proxy = build_proxy(:factory)
|
||||||
|
|
||||||
proxy.sequence(:sequence)
|
proxy.sequence(:sequence)
|
||||||
|
|
||||||
expect(FactoryBot::Sequence).to have_received(:new).
|
expect(FactoryBot::Sequence).to have_received(:new).with(:sequence)
|
||||||
with("__factory_sequence__")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it "creates a new sequence with an overridden starting vaue" do
|
it "creates a new sequence with an overridden starting vaue" do
|
||||||
proxy = build_proxy(:factory)
|
proxy = build_proxy(:factory)
|
||||||
proxy.sequence(:sequence, "C")
|
override = "override"
|
||||||
|
|
||||||
|
proxy.sequence(:sequence, override)
|
||||||
|
|
||||||
expect(FactoryBot::Sequence).to have_received(:new).
|
expect(FactoryBot::Sequence).to have_received(:new).
|
||||||
with("__factory_sequence__", "C")
|
with(:sequence, override)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "creates a new sequence with a block" do
|
it "creates a new sequence with a block" do
|
||||||
|
@ -126,7 +128,7 @@ describe FactoryBot::DefinitionProxy, "#sequence" do
|
||||||
proxy.sequence(:sequence, 1, &sequence_block)
|
proxy.sequence(:sequence, 1, &sequence_block)
|
||||||
|
|
||||||
expect(FactoryBot::Sequence).to have_received(:new).
|
expect(FactoryBot::Sequence).to have_received(:new).
|
||||||
with("__factory_sequence__", 1, &sequence_block)
|
with(:sequence, 1, &sequence_block)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue