Skip to content

Commit

Permalink
Sequences support Enumerators
Browse files Browse the repository at this point in the history
This introduces an EnumeratorAdapter so everything coming in looks like
an Enumerator. It doesn't use the adapter if the #peek method exists on
the object.

This allows for sequences like:

    sequence(:cities, %w[Boston Atlanta Detroit Seattle].cycle)

This also makes it easier to cycle through arrays and ranges, since they
can be converted to Enumerators rather easily.

    sequence(:month, (1..12).to_enum)
    sequence(:month, %w[foo bar baz].to_enum)

This doesn't handle when calling Range#step out of the box, because
Ruby returns an Enumerator but ActiveSupport 3.x returns an array,
meaning #to_enum still needs to be called.

Closes thoughtbot#339, thoughtbot#378
  • Loading branch information
joshuaclayton committed May 13, 2012
1 parent d0e56fe commit 7b38221
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 2 deletions.
24 changes: 22 additions & 2 deletions lib/factory_girl/sequence.rb
Expand Up @@ -13,16 +13,36 @@ def initialize(name, *args, &proc)
options = args.extract_options!
@value = args.first || 1
@aliases = options.fetch(:aliases) { [] }

if !@value.respond_to?(:peek)
@value = EnumeratorAdapter.new(@value)
end
end

def next
@proc ? @proc.call(@value) : @value
@proc ? @proc.call(@value.peek) : @value.peek
ensure
@value = @value.next
@value.next
end

def names
[@name] + @aliases
end

private

class EnumeratorAdapter
def initialize(value)
@value = value
end

def peek
@value
end

def next
@value = @value.next
end
end
end
end
10 changes: 10 additions & 0 deletions spec/factory_girl/sequence_spec.rb
Expand Up @@ -65,4 +65,14 @@
its(:next) { should == "B" }
end
end

describe "iterating over items in an enumerator" do
subject { FactoryGirl::Sequence.new(:name, %w[foo bar].to_enum) {|n| "=#{n}" } }

it "navigates to the next items until no items remain" do
subject.next.should == "=foo"
subject.next.should == "=bar"
expect { subject.next }.to raise_error(StopIteration)
end
end
end

0 comments on commit 7b38221

Please sign in to comment.