Module: Stepford::FactoryGirl
- Defined in:
- lib/stepford/factory_girl.rb
Overview
A proxy for FactoryGirl that automatically recursively creates/builds/stubbed factories for null=false and/or presence validated associations.
Lets you specify method name and arguments/options to factory girl for associations.
e.g. if the following is required:
-
Bar has a required association called house_special which uses the :beer factory, and we have a block we want to send into it
-
Beer has specials that you want to build as a list of 3 using the :tuesday_special_offer factory
then you could set that up like this:
Stepford::FactoryGirl.create_list(:bar, with_factory_options: {
house_special: [:create, :beer, {blk: ->(beer) do; beer.bubbles.create(attributes_for(:bubbles)); end}],
specials: [:build_list, :tuesday_special_offer, 3]
}) do
# the block you would send to FactoryGirl.create_list(:foo) would go here
end
Constant Summary collapse
- OPTIONS =
[ :debug ]
Class Method Summary collapse
- .build(*args, &block) ⇒ Object
- .build_list(*args, &block) ⇒ Object
- .build_stubbed(*args, &block) ⇒ Object
- .configure(&blk) ⇒ Object
-
.create(*args, &block) ⇒ Object
switched to this from method_missing to avoid method trying to handle mistaken calls.
- .create_list(*args, &block) ⇒ Object
- .debugargs(args) ⇒ Object
- .deep_dup(o) ⇒ Object
- .handle_factory_girl_method(m, *args, &block) ⇒ Object
-
.method_missing(m, *args, &block) ⇒ Object
pass everything else to FactoryGirl to try to handle (can’t reflect in current version to find what it handles).
Class Method Details
.build(*args, &block) ⇒ Object
144 |
# File 'lib/stepford/factory_girl.rb', line 144 def build(*args, &block); handle_factory_girl_method(:build, *args, &block); end |
.build_list(*args, &block) ⇒ Object
145 |
# File 'lib/stepford/factory_girl.rb', line 145 def build_list(*args, &block); handle_factory_girl_method(:build_list, *args, &block); end |
.build_stubbed(*args, &block) ⇒ Object
146 |
# File 'lib/stepford/factory_girl.rb', line 146 def build_stubbed(*args, &block); handle_factory_girl_method(:build_stubbed, *args, &block); end |
.configure(&blk) ⇒ Object
26 |
# File 'lib/stepford/factory_girl.rb', line 26 def configure(&blk); class_eval(&blk); end |
.create(*args, &block) ⇒ Object
switched to this from method_missing to avoid method trying to handle mistaken calls
142 |
# File 'lib/stepford/factory_girl.rb', line 142 def create(*args, &block); handle_factory_girl_method(:create, *args, &block); end |
.create_list(*args, &block) ⇒ Object
143 |
# File 'lib/stepford/factory_girl.rb', line 143 def create_list(*args, &block); handle_factory_girl_method(:create_list, *args, &block); end |
.debugargs(args) ⇒ Object
180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/stepford/factory_girl.rb', line 180 def debugargs(args) result = [] args.each do |arg| if arg.is_a?(Hash) result << "{#{arg.keys.collect{|key|"#{key} = (#{arg[key].class.name})"}.join(', ')}}" else result << "#{arg.inspect}," end end result.join('') end |
.deep_dup(o) ⇒ Object
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
# File 'lib/stepford/factory_girl.rb', line 150 def deep_dup(o) result = nil if o.is_a?(Hash) result = {} o.keys.each do |key| result[deep_dup(key)] = deep_dup(o[key]) end elsif o.is_a?(Array) result = [] o.each do |value| result << deep_dup(value) end elsif [NilClass,FalseClass,TrueClass,Symbol,Numeric,Class,Module].any?{|c|o.is_a?(c)} result = o elsif o.is_a?(BigDecimal) # ActiveSupport v3.2.8 checks duplicable? for BigDecimal by testing it, so we'll just try to dup the value itself result = o begin result = o.dup rescue TypeError # can't dup end elsif o.is_a?(Object) result = o.dup else result = o end result end |
.handle_factory_girl_method(m, *args, &block) ⇒ Object
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/stepford/factory_girl.rb', line 28 def handle_factory_girl_method(m, *args, &block) #puts "#{' ' * @@indent}handling Stepford::FactoryGirl.#{m}(#{args.inspect})" if ::Stepford::FactoryGirl.debug? if args && args.size > 0 # call Stepford::FactoryGirl.* on any not null associations recursively model_sym = args[0].to_sym model_class = args[0].to_s.camelize.constantize args = args.dup # need local version because we'll be dup'ing the options hash to add things to set prior to create/build = args.last if .is_a?(Hash) # keep them separate = = deep_dup() args[(args.size - 1)] = # need to set the dup'd options else # keep them separate = {} = {} args << # need to add options to set associations end [:with_factory_options] = {} unless [:with_factory_options] = [:with_factory_options] [:nesting_breadcrumbs] = [] unless [:nesting_breadcrumbs] = [:nesting_breadcrumbs] << [args[0]] if ::Stepford::FactoryGirl.debug? puts "#{.join('>')} start. args=#{debugargs(args)}" end model_class.reflections.each do |association_name, reflection| assc_sym = reflection.name.to_sym next if [assc_sym] || [reflection.foreign_key.to_sym] # || reflection.macro != :belongs_to clas_sym = reflection.class_name.underscore.to_sym has_presence_validator = model_class.validators_on(assc_sym).collect{|v|v.class}.include?(::ActiveModel::Validations::PresenceValidator) required = reflection.foreign_key ? (has_presence_validator || model_class.columns.any?{|c| !c.null && c.name.to_sym == reflection.foreign_key.to_sym}) : false = ? ([[clas_sym, assc_sym]] || [clas_sym]) : nil has_presence_validator = model_class.validators_on(assc_sym).collect{|v|v.class}.include?(ActiveModel::Validations::PresenceValidator) required = false if reflection.macro == :belongs_to # note: supports composite_primary_keys gem which stores primary_key as an array foreign_key_is_also_primary_key = Array.wrap(model_class.primary_key).collect{|pk|pk.to_sym}.include?(reflection.foreign_key.to_sym) is_not_null_fkey_that_is_not_primary_key = model_class.columns.any?{|c| !c.null && c.name.to_sym == reflection.foreign_key.to_sym && !foreign_key_is_also_primary_key} required = is_not_null_fkey_that_is_not_primary_key || has_presence_validator else # no nullable metadata on column if no foreign key in this table. we'd figure out the null requirement on the column if inspecting the child model required = has_presence_validator end if required << ["a:#{assc_sym}"] if = .dup = args.last blk = .is_a?(Hash) ? .delete(:blk) : nil begin if blk #puts "#{' ' * @@indent}FactoryGirl.__send__(#{method_args_and_options.inspect}, &blk)" if ::Stepford::FactoryGirl.debug? [assc_sym] = ::FactoryGirl.__send__(*, &blk) else #puts "#{' ' * @@indent}FactoryGirl.__send__(#{method_args_and_options.inspect})" if ::Stepford::FactoryGirl.debug? [assc_sym] = ::FactoryGirl.__send__(*) end rescue ActiveRecord::RecordInvalid => e puts "#{.join('>')}: FactoryGirl.__send__(#{.inspect}): #{e}#{::Stepford::FactoryGirl.debug? ? "\n#{e.backtrace.join("\n")}" : ''}" raise e end else if reflection.macro == :has_many [assc_sym] = ::Stepford::FactoryGirl.create_list(clas_sym, 2, ) else [assc_sym] = ::Stepford::FactoryGirl.create(clas_sym, ) end end .pop end end end if defined?() if ::Stepford::FactoryGirl.debug? puts "#{.join('>')} end" puts "#{.join('>')} FactoryGirl.#{m}(#{debugargs(args)})" end .pop end # clean-up before sending to FactoryGirl if args.last.is_a?(Hash) (args.last).delete(:with_factory_options) (args.last).delete(:nesting_breadcrumbs) end begin result = ::FactoryGirl.__send__(m, *args, &block) rescue ActiveRecord::RecordInvalid => e puts "#{.join('>')}: FactoryGirl.#{m}(#{args.inspect}): #{e}#{::Stepford::FactoryGirl.debug? ? "\n#{e.backtrace.join("\n")}" : ''}" if defined?() raise e end if args.last.is_a?(Hash) && defined?() && .size > 0 args.last[:nesting_breadcrumbs] = end result end |
.method_missing(m, *args, &block) ⇒ Object
pass everything else to FactoryGirl to try to handle (can’t reflect in current version to find what it handles)
148 |
# File 'lib/stepford/factory_girl.rb', line 148 def method_missing(m, *args, &block); ::FactoryGirl.__send__(m, *args, &block); end |