stepford 0.11.0 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -40,10 +40,12 @@ By default autogenerated factories just have required attributes, e.g.:
40
40
 
41
41
  FactoryGirl.define do
42
42
 
43
- factory :post do
43
+ factory :novel do
44
44
  created_at { 2.weeks.ago }
45
45
  name 'Test Name'
46
46
  price 1.23
47
+ sequence(:isbn)
48
+ sequence(:ean)
47
49
  trait :with_summary do; template 'Test Summary'; end
48
50
  updated_at { 2.weeks.ago }
49
51
  end
@@ -56,7 +58,7 @@ But you can have it autogenerate lots of the FactoryGirl bells and whistles:
56
58
 
57
59
  FactoryGirl.define do
58
60
 
59
- factory :post do
61
+ factory :novel do
60
62
  author
61
63
  association :edited_by, factory: :user
62
64
  FactoryGirl.create_list :comments, 2
@@ -66,6 +68,8 @@ But you can have it autogenerate lots of the FactoryGirl bells and whistles:
66
68
  created_at { 2.weeks.ago }
67
69
  name 'Test Name'
68
70
  price 1.23
71
+ sequence(:isbn)
72
+ sequence(:ean)
69
73
  trait :with_summary do; template 'Test Summary'; end
70
74
  updated_at { 2.weeks.ago }
71
75
  end
@@ -252,9 +256,11 @@ If working with a legacy schema, you may have models with foreign_key columns th
252
256
 
253
257
  If the ActiveRecord column `null` property for the attribute is true for the attribute or foreign key for the association, or if there is a presence validator for an attribute or foreign key for the association, then that attribute or association will be defined by the default factory.
254
258
 
255
- Currently uniqueness constraints are ignored and must be handled by FactoryGirl sequence or similar if not automatically populated by your model or the database, e.g. in your factory, if username uniqueness is enforced by a unique constraint on the database-side, you'll need to do something like this manually in the factory:
259
+ Uniqueness constraints on the model are handled by the following being generated in the factory, which works for strings and numbers:
256
260
 
257
- sequence(:username) {|n| "user#{n}" }
261
+ sequence(:my_attribute)
262
+
263
+ If you have a formatting constraint, some other constraint, or don't like the format of the data in the factories, see the [Factory Girl][factory_girl] documentation to find out how to customize your factories.
258
264
 
259
265
  ##### Testing Factories
260
266
 
@@ -347,12 +353,6 @@ or referring to created objects through associations, though he said multiple ne
347
353
 
348
354
  This is the reason we wrote the Stepford's Factory Girl proxy and helper rspec methods (see above). It automatically determines what needs to be set in what order and does create, create_list or build, build_list, etc. automatically.
349
355
 
350
- Unfortunately, it still has trouble with fkey constraints:
351
-
352
- insert or update on table "foobars" violates foreign key constraint "some_foreign_key_contraint_name"
353
-
354
- Working on that.
355
-
356
356
  ### License
357
357
 
358
358
  Copyright (c) 2012 Gary S. Weaver, released under the [MIT license][lic].
@@ -18,20 +18,16 @@ module Stepford
18
18
  # end
19
19
  module FactoryGirl
20
20
  OPTIONS = [
21
- :debug,
22
- :stop_circular_refs
21
+ :debug
23
22
  ]
24
23
 
25
24
  class << self
26
- @@breadcrumbs = []
27
-
28
25
  OPTIONS.each{|o|attr_accessor o; define_method("#{o}?".to_sym){!!send("#{o}")}}
29
26
  def configure(&blk); class_eval(&blk); end
30
27
 
31
28
  def handle_factory_girl_method(m, *args, &block)
32
- @@breadcrumbs << [args[0]] if ::Stepford::FactoryGirl.debug?
29
+
33
30
  #puts "#{' ' * @@indent}handling Stepford::FactoryGirl.#{m}(#{args.inspect})" if ::Stepford::FactoryGirl.debug?
34
- puts "#{@@breadcrumbs.join('>')} start" if ::Stepford::FactoryGirl.debug?
35
31
 
36
32
  if args && args.size > 0
37
33
  # call Stepford::FactoryGirl.* on any not null associations recursively
@@ -52,14 +48,16 @@ module Stepford
52
48
  args << options # need to add options to set associations
53
49
  end
54
50
 
55
- if ::Stepford::FactoryGirl.debug?
56
- print "#{@@breadcrumbs.join('>')} args="
57
- debugargs(args)
58
- puts
59
- end
60
-
61
51
  options[:with_factory_options] = {} unless options[:with_factory_options]
62
52
  with_factory_options = options[:with_factory_options]
53
+
54
+ orig_options[:nesting_breadcrumbs] = [] unless orig_options[:nesting_breadcrumbs]
55
+ breadcrumbs = orig_options[:nesting_breadcrumbs]
56
+ breadcrumbs << [args[0]]
57
+
58
+ if ::Stepford::FactoryGirl.debug?
59
+ puts "#{breadcrumbs.join('>')} start. args=#{debugargs(args)}"
60
+ end
63
61
 
64
62
  model_class.reflections.each do |association_name, reflection|
65
63
  assc_sym = reflection.name.to_sym
@@ -83,18 +81,23 @@ module Stepford
83
81
  end
84
82
 
85
83
  if required
86
- @@breadcrumbs << ["a:#{assc_sym}"] if ::Stepford::FactoryGirl.debug?
84
+ breadcrumbs << ["a:#{assc_sym}"]
87
85
  if orig_method_args_and_options
88
86
  method_args_and_options = orig_method_args_and_options.dup
89
87
  method_options = args.last
90
88
  blk = method_options.is_a?(Hash) ? method_args_and_options.delete(:blk) : nil
91
- if blk
92
- #puts "#{' ' * @@indent}FactoryGirl.__send__(#{method_args_and_options.inspect}, &blk)" if ::Stepford::FactoryGirl.debug?
93
- options[assc_sym] = ::FactoryGirl.__send__(*method_args_and_options, &blk)
94
- else
95
- #puts "#{' ' * @@indent}FactoryGirl.__send__(#{method_args_and_options.inspect})" if ::Stepford::FactoryGirl.debug?
96
- options[assc_sym] = ::FactoryGirl.__send__(*method_args_and_options)
97
- end
89
+ begin
90
+ if blk
91
+ #puts "#{' ' * @@indent}FactoryGirl.__send__(#{method_args_and_options.inspect}, &blk)" if ::Stepford::FactoryGirl.debug?
92
+ options[assc_sym] = ::FactoryGirl.__send__(*method_args_and_options, &blk)
93
+ else
94
+ #puts "#{' ' * @@indent}FactoryGirl.__send__(#{method_args_and_options.inspect})" if ::Stepford::FactoryGirl.debug?
95
+ options[assc_sym] = ::FactoryGirl.__send__(*method_args_and_options)
96
+ end
97
+ rescue ActiveRecord::RecordInvalid => e
98
+ puts "#{breadcrumbs.join('>')}: FactoryGirl.__send__(#{method_args_and_options.inspect}): #{e}#{::Stepford::FactoryGirl.debug? ? "\n#{e.backtrace.join("\n")}" : ''}"
99
+ raise e
100
+ end
98
101
  else
99
102
  if reflection.macro == :has_many
100
103
  options[assc_sym] = ::Stepford::FactoryGirl.create_list(clas_sym, 2, orig_options)
@@ -102,25 +105,37 @@ module Stepford
102
105
  options[assc_sym] = ::Stepford::FactoryGirl.create(clas_sym, orig_options)
103
106
  end
104
107
  end
105
- @@breadcrumbs.pop if ::Stepford::FactoryGirl.debug?
108
+ breadcrumbs.pop
106
109
  end
107
110
  end
108
111
  end
109
112
 
113
+ if defined?(breadcrumbs)
114
+ if ::Stepford::FactoryGirl.debug?
115
+ puts "#{breadcrumbs.join('>')} end"
116
+ puts "#{breadcrumbs.join('>')} FactoryGirl.#{m}(#{debugargs(args)})"
117
+ end
118
+ breadcrumbs.pop
119
+ end
120
+
110
121
  # clean-up before sending to FactoryGirl
111
- (args.last).delete(:with_factory_options) if args.last.is_a?(Hash)
112
-
113
- if ::Stepford::FactoryGirl.debug?
114
- puts "#{@@breadcrumbs.join('>')} end"
115
- puts
116
- print "#{@@breadcrumbs.join('>')} FactoryGirl.#{m}("
117
- debugargs(args)
118
- puts ")"
119
- puts
120
- @@breadcrumbs.pop
122
+ if args.last.is_a?(Hash)
123
+ (args.last).delete(:with_factory_options)
124
+ (args.last).delete(:nesting_breadcrumbs)
121
125
  end
122
126
 
123
- ::FactoryGirl.__send__(m, *args, &block)
127
+ begin
128
+ result = ::FactoryGirl.__send__(m, *args, &block)
129
+ rescue ActiveRecord::RecordInvalid => e
130
+ puts "#{breadcrumbs.join('>')}: FactoryGirl.#{m}(#{args.inspect}): #{e}#{::Stepford::FactoryGirl.debug? ? "\n#{e.backtrace.join("\n")}" : ''}" if defined?(breadcrumbs)
131
+ raise e
132
+ end
133
+
134
+ if args.last.is_a?(Hash) && defined?(breadcrumbs) && breadcrumbs.size > 0
135
+ args.last[:nesting_breadcrumbs] = breadcrumbs
136
+ end
137
+
138
+ result
124
139
  end
125
140
 
126
141
  # switched to this from method_missing to avoid method trying to handle mistaken calls
@@ -163,15 +178,15 @@ module Stepford
163
178
  end
164
179
 
165
180
  def debugargs(args)
181
+ result = []
166
182
  args.each do |arg|
167
183
  if arg.is_a?(Hash)
168
- print "{"
169
- print arg.keys.collect{|key|"#{key} = (#{arg[key].class.name})"}.join(', ')
170
- print "}"
184
+ result << "{#{arg.keys.collect{|key|"#{key} = (#{arg[key].class.name})"}.join(', ')}}"
171
185
  else
172
- print "#{arg.inspect},"
186
+ result << "#{arg.inspect},"
173
187
  end
174
188
  end
189
+ result.join('')
175
190
  end
176
191
  end
177
192
  end
@@ -19,7 +19,7 @@ module Stepford
19
19
  excluded_attributes << reflection.foreign_key.to_sym if reflection.foreign_key
20
20
  assc_sym = reflection.name.to_sym
21
21
  clas_sym = reflection.class_name.underscore.to_sym
22
- # if has a foreign key, then if NOT NULL or is a presence validate, the association is required and should be output. unfortunately this could mean a circular reference that will have to be manually fixed
22
+ # if has a foreign key, then if NOT NULL or is a presence validate, the association is required and should be output. unfortunately this could mean a circular reference that will have to be manually fixed
23
23
  has_presence_validator = model_class.validators_on(assc_sym).collect{|v|v.class}.include?(ActiveModel::Validations::PresenceValidator)
24
24
  required = reflection.foreign_key ? (has_presence_validator || model_class.columns.any?{|c| !c.null && c.name.to_sym == reflection.foreign_key.to_sym}) : false
25
25
  should_be_trait = !(options[:associations] || (options[:include_required_associations] && required)) && options[:association_traits]
@@ -41,7 +41,13 @@ module Stepford
41
41
  }.compact.sort.each {|l|factory << l}
42
42
  model_class.columns.sort_by {|c|[c.name]}.each {|c|
43
43
  if !excluded_attributes.include?(c.name.to_sym) && !(c.name.downcase.end_with?('_id') && options[:exclude_all_ids]) && (options[:attributes] || !c.null)
44
- factory << "#{is_reserved?(c.name) ? 'self.' : ''}#{c.name} #{Stepford::Common.value_for(c)}"
44
+ has_uniqueness_validator = model_class.validators_on(c.name.to_sym).collect{|v|v.class}.include?(ActiveRecord::Validations::UniquenessValidator)
45
+ if has_uniqueness_validator
46
+ #TODO: specialize for different data types
47
+ factory << "sequence(#{c.name.to_sym.inspect})"
48
+ else
49
+ factory << "#{is_reserved?(c.name) ? 'self.' : ''}#{c.name} #{Stepford::Common.value_for(c)}"
50
+ end
45
51
  elsif options[:attribute_traits]
46
52
  if c.type == :boolean
47
53
  factory << "trait #{c.name.underscore.to_sym.inspect} do; #{is_reserved?(c.name) ? 'self.' : ''}#{c.name} true; end"
@@ -1,3 +1,3 @@
1
1
  module Stepford
2
- VERSION = '0.11.0'
2
+ VERSION = '0.12.0'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stepford
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.0
4
+ version: 0.12.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors: