From 3b5a8e184e14a632874087d780974903ca136ec5 Mon Sep 17 00:00:00 2001 From: Yury Kotov Date: Sun, 3 Jul 2016 13:37:35 +0300 Subject: [PATCH] Ability to create collections of items --- README.md | 10 ++++++++++ lib/cranky/factory.rb | 33 +++++++++++++++++---------------- spec/cranky_spec.rb | 5 +++++ spec/spec_helper.rb | 4 ++++ 4 files changed, 36 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index db92036..60a003b 100644 --- a/README.md +++ b/README.md @@ -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... diff --git a/lib/cranky/factory.rb b/lib/cranky/factory.rb index 682a1de..cad2686 100644 --- a/lib/cranky/factory.rb +++ b/lib/cranky/factory.rb @@ -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) @@ -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 @@ -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 @@ -100,7 +101,7 @@ 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 @@ -108,7 +109,7 @@ 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 diff --git a/spec/cranky_spec.rb b/spec/cranky_spec.rb index bfb20d5..df7b94d 100644 --- a/spec/cranky_spec.rb +++ b/spec/cranky_spec.rb @@ -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 => "indy@home.com", :role => :dog, :unique => :yep) u.name.should == "Indy" diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 2a0596e..24acdc5 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -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