Skip to content

Commit

Permalink
Ability to create collections of items
Browse files Browse the repository at this point in the history
  • Loading branch information
beorc committed Jul 18, 2016
1 parent eb52c47 commit 3b5a8e1
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 16 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,16 @@ def apply_trait_manager_to_user(user)
end
~~~

You can create collections...

~~~ruby
Factory.create(:users_collection)

def users_collection
3.time.map { build(:user) }
end
~~~

## Helpers

Of course its nice to get some help...
Expand Down
33 changes: 17 additions & 16 deletions lib/cranky/factory.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,23 @@ class Factory
def initialize
# Factory jobs can be nested, i.e. a factory method can itself invoke another factory method to
# build a dependent object. In this case jobs the jobs are pushed into a pipeline and executed
# in a last in first out order.
# in a last in first out order.
@pipeline = []
@n = 0
@errors = []
end

def build(what, overrides={})
crank_it(what, overrides)
end

def create(what, overrides={})
item = build(what, overrides)
item.save
Array(item).each(&:save)
item
end

# Reset the factory instance, clear all instance variables
# Reset the factory instance, clear all instance variables
def reset
self.instance_variables.each do |var|
instance_variable_set(var, nil)
Expand All @@ -34,17 +34,18 @@ def attributes_for(what, attrs={})
build(what, attrs.merge(:_return_attributes => true))
end

# Can be left in your tests as an alternative to build and to warn if your factory method
# ever starts producing invalid instances
# Can be left in your tests as an alternative to build and to warn if your factory method
# ever starts producing invalid instances
def debug(*args)
item = build(*args)
if !item.valid?
if item.errors.respond_to?("messages")
errors = item.errors.messages
item = build(*args)
invalid_item = Array(item).find(&:invalid?)
if invalid_item
if invalid_item.errors.respond_to?(:messages)
errors = invalid_item.errors.messages
else
errors = item.errors
errors = invalid_item.errors
end
raise "Oops, the #{item.class} created by the Factory has the following errors: #{errors}"
raise "Oops, the #{invalid_item.class} created by the Factory has the following errors: #{errors}"
end
item
end
Expand Down Expand Up @@ -86,10 +87,10 @@ def crank_it(what, overrides)
item
end

# This method actually makes the required object instance, it gets called by the users factory
# This method actually makes the required object instance, it gets called by the users factory
# method, where the name 'define' makes more sense than it does here!
def define(defaults={})
current_job.defaults = defaults
current_job.defaults = defaults
current_job.execute
end

Expand All @@ -100,15 +101,15 @@ def inherit(what, overrides={})
end

def current_job
@pipeline.last
@pipeline.last
end

# Returns a hash containing any top-level overrides passed in when the current factory was invoked
def options
current_job.overrides
end

# Adds a new job to the pipeline then yields to the caller to execute it
# Adds a new job to the pipeline then yields to the caller to execute it
def new_job(what, overrides)
@pipeline << Job.new(what, overrides)
yield
Expand Down
5 changes: 5 additions & 0 deletions spec/cranky_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@
crank!(:user).saved?.should == true
end

it "does save each item in the collection when generated via create or crank!" do
Factory.create(:users_collection).select { |u| !u.saved? }.should be_empty
crank!(:users_collection).select { |u| !u.saved? }.should be_empty
end

it "allows all attributes to be overriden in the call" do
u = Factory.build(:user, :name => "Indy", :email => "[email protected]", :role => :dog, :unique => :yep)
u.name.should == "Indy"
Expand Down
4 changes: 4 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ def user_hash
:role => :user
end

def users_collection
3.times.map { build(:user) }
end

def apply_trait_manager_to_user_manually(user)
user.role = :manager
end
Expand Down

0 comments on commit 3b5a8e1

Please sign in to comment.