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 +10 -10
- data/lib/stepford/factory_girl.rb +51 -36
- data/lib/stepford/factory_girl_generator.rb +8 -2
- data/lib/stepford/version.rb +1 -1
- metadata +1 -1
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 :
|
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 :
|
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
|
-
|
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(:
|
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
|
-
|
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
|
-
|
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
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
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
|
-
|
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
|
-
|
112
|
-
|
113
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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"
|
data/lib/stepford/version.rb
CHANGED