diff --git a/gemfiles/3.0.gemfile.lock b/gemfiles/3.0.gemfile.lock index 55d65236..f7fd316 100644 --- a/gemfiles/3.0.gemfile.lock +++ b/gemfiles/3.0.gemfile.lock @@ -1,5 +1,5 @@ PATH - remote: /Users/mjankowski/Development/OpenSource/factory_girl + remote: /Users/joshuaclayton/dev/gems/factory_girl specs: factory_girl (4.1.0) activesupport (>= 3.0.0) diff --git a/gemfiles/3.1.gemfile.lock b/gemfiles/3.1.gemfile.lock index 18e1ae9..0fe4189 100644 --- a/gemfiles/3.1.gemfile.lock +++ b/gemfiles/3.1.gemfile.lock @@ -1,5 +1,5 @@ PATH - remote: /Users/mjankowski/Development/OpenSource/factory_girl + remote: /Users/joshuaclayton/dev/gems/factory_girl specs: factory_girl (4.1.0) activesupport (>= 3.0.0) diff --git a/gemfiles/3.2.gemfile.lock b/gemfiles/3.2.gemfile.lock index fcc7e09..5491e8e 100644 --- a/gemfiles/3.2.gemfile.lock +++ b/gemfiles/3.2.gemfile.lock @@ -1,5 +1,5 @@ PATH - remote: /Users/mjankowski/Development/OpenSource/factory_girl + remote: /Users/joshuaclayton/dev/gems/factory_girl specs: factory_girl (4.1.0) activesupport (>= 3.0.0) diff --git a/lib/factory_girl/definition_proxy.rb b/lib/factory_girl/definition_proxy.rb index 2a05e50..79c9789 100644 --- a/lib/factory_girl/definition_proxy.rb +++ b/lib/factory_girl/definition_proxy.rb @@ -108,7 +108,7 @@ module FactoryGirl # Except that no globally available sequence will be defined. def sequence(name, *args, &block) sequence = Sequence.new(name, *args, &block) - add_attribute(name) { sequence.next } + add_attribute(name) { increment_sequence(sequence) } end # Adds an attribute that builds an association. The associated instance will diff --git a/lib/factory_girl/evaluator.rb b/lib/factory_girl/evaluator.rb index de7b105..fbf2e16 100644 --- a/lib/factory_girl/evaluator.rb +++ b/lib/factory_girl/evaluator.rb @@ -42,10 +42,18 @@ module FactoryGirl end end + def respond_to_missing?(method_name, include_private = false) + @instance.respond_to?(method_name) || SyntaxRunner.new.respond_to?(method_name) + end + def __override_names__ @overrides.keys end + def increment_sequence(sequence) + sequence.next(self) + end + def self.attribute_list AttributeList.new.tap do |list| attribute_lists.each do |attribute_list| diff --git a/lib/factory_girl/sequence.rb b/lib/factory_girl/sequence.rb index 5b2ae03..1ec88c7 100644 --- a/lib/factory_girl/sequence.rb +++ b/lib/factory_girl/sequence.rb @@ -19,10 +19,16 @@ module FactoryGirl end end - def next - @proc ? @proc.call(@value.peek) : @value.peek + def next(scope = nil) + if @proc && scope + scope.instance_exec(value, &@proc) + elsif @proc + @proc.call(value) + else + value + end ensure - @value.next + increment_value end def names @@ -31,6 +37,14 @@ module FactoryGirl private + def value + @value.peek + end + + def increment_value + @value.next + end + class EnumeratorAdapter def initialize(value) @value = value diff --git a/spec/acceptance/sequence_context_spec.rb b/spec/acceptance/sequence_context_spec.rb new file mode 100644 index 0000000..221ca2d --- /dev/null +++ b/spec/acceptance/sequence_context_spec.rb @@ -0,0 +1,52 @@ +require 'spec_helper' + +describe 'sequences are evaluated in the correct context' do + before do + define_class("User") do + attr_accessor :id + + def awesome + 'aw yeah' + end + end + end + + it 'builds a sequence calling sprintf correctly' do + FactoryGirl.define do + factory :sequence_with_sprintf, class: User do + sequence(:id) {|n| sprintf("foo%d", n) } + end + end + + FactoryGirl.build(:sequence_with_sprintf).id.should == 'foo1' + end + + it 'invokes the correct method on the instance' do + FactoryGirl.define do + factory :sequence_with_public_method, class: User do + sequence(:id) {|n| public_method(:awesome).call } + end + end + + FactoryGirl.build(:sequence_with_public_method).id.should == 'aw yeah' + end + + it 'invokes a method with no arguments on the instance' do + FactoryGirl.define do + factory :sequence_with_frozen, class: User do + sequence(:id) {|n| frozen? } + end + end + + FactoryGirl.build(:sequence_with_frozen).id.should be_false + end + + it 'allows direct reference of a method in a sequence' do + FactoryGirl.define do + factory :sequence_referencing_attribute_directly, class: User do + sequence(:id) {|n| "#{awesome}#{n}" } + end + end + FactoryGirl.build(:sequence_referencing_attribute_directly).id.should == 'aw yeah1' + end +end diff --git a/spec/factory_girl/sequence_spec.rb b/spec/factory_girl/sequence_spec.rb index 0018b94..a246275 100644 --- a/spec/factory_girl/sequence_spec.rb +++ b/spec/factory_girl/sequence_spec.rb @@ -75,4 +75,21 @@ describe FactoryGirl::Sequence do expect { subject.next }.to raise_error(StopIteration) end end + + describe "a custom sequence and scope" do + subject { FactoryGirl::Sequence.new(:name, 'A') {|n| "=#{n}#{foo}" } } + let(:scope) { stub('scope', foo: 'attribute') } + + it 'increments within the correct scope' do + subject.next(scope).should == '=Aattribute' + end + + describe 'when incrementing' do + before { subject.next(scope) } + + it 'increments within the correct scope' do + subject.next(scope).should == '=Battribute' + end + end + end end