class FactoryBot::Sequence
Sequences are defined using sequence within a FactoryBot.define block. Sequence values are generated using next. @api private
Attributes
Public Class Methods
Source
# File lib/factory_bot/sequence.rb, line 10 def self.find(*uri_parts) if uri_parts.empty? fail ArgumentError, "wrong number of arguments, expected 1+)" else find_by_uri FactoryBot::UriManager.build_uri(*uri_parts) end end
Source
# File lib/factory_bot/sequence.rb, line 18 def self.find_by_uri(uri) uri = uri.to_sym FactoryBot::Internal.sequences.to_a.find { |seq| seq.has_uri?(uri) } || FactoryBot::Internal.inline_sequences.find { |seq| seq.has_uri?(uri) } end
Source
# File lib/factory_bot/sequence.rb, line 24 def initialize(name, *args, &proc) options = args.extract_options! @name = name @proc = proc @aliases = options.fetch(:aliases, []).map(&:to_sym) @uri_manager = FactoryBot::UriManager.new(names, paths: options[:uri_paths]) @value = args.first || 1 unless @value.respond_to?(:peek) @value = EnumeratorAdapter.new(@value) end end
Public Instance Methods
Source
# File lib/factory_bot/sequence.rb, line 61 def for_factory?(test_factory_name) FactoryBot::Internal.factory_by_name(factory_name).names.include?(test_factory_name.to_sym) end
Source
# File lib/factory_bot/sequence.rb, line 53 def has_name?(test_name) names.include?(test_name.to_sym) end
Source
# File lib/factory_bot/sequence.rb, line 57 def has_uri?(uri) uri_manager.include?(uri) end
Source
# File lib/factory_bot/sequence.rb, line 37 def next(scope = nil) if @proc && scope scope.instance_exec(value, &@proc) elsif @proc @proc.call(value) else value end ensure increment_value end
Source
# File lib/factory_bot/sequence.rb, line 73 def set_value(new_value) if can_set_value_directly?(new_value) @value.set_value(new_value) elsif can_set_value_by_index? set_value_by_index(new_value) else seek_value(new_value) end end
If itβs an Integer based sequence, set the new value directly, else rewind and seek from the beginning until a match is found.
Private Instance Methods
Source
# File lib/factory_bot/sequence.rb, line 97 def can_set_value_by_index? @value.respond_to?(:find_index) end
Source
# File lib/factory_bot/sequence.rb, line 142 def can_set_value_directly?(value) return false unless value.is_a?(Integer) return false unless @value.is_a?(EnumeratorAdapter) @value.integer_value? end
Source
# File lib/factory_bot/sequence.rb, line 148 def fail_value_not_found(value) fail ArgumentError, "Unable to find '#{value}' in the sequence." end
Source
# File lib/factory_bot/sequence.rb, line 93 def increment_value @value.next end
Source
# File lib/factory_bot/sequence.rb, line 134 def reset_original_value(original_value) @value.rewind until @value.peek == original_value increment_value end end
Source
# File lib/factory_bot/sequence.rb, line 114 def seek_value(value) original_value = @value.peek # rewind and search for the new value @value.rewind Timeout.timeout(FactoryBot.sequence_setting_timeout) do loop do return if @value.peek == value increment_value end # loop auto-recues a StopIteration error, so if we # reached this point, re-raise it now fail StopIteration end rescue Timeout::Error, StopIteration reset_original_value(original_value) fail_value_not_found(value) end
Rewind index and seek until the value is found or the max attempts have been tried. If not found, the sequence is rewound to its original value
Source
# File lib/factory_bot/sequence.rb, line 104 def set_value_by_index(value) index = @value.find_index(value) || fail_value_not_found(value) @value.rewind index.times { @value.next } end
Set to the given value, or fail if not found