stepford 0.9.3 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +90 -18
- data/lib/stepford/circular_ref_checker.rb +11 -6
- data/lib/stepford/factory_girl.rb +103 -83
- data/lib/stepford/factory_girl_rspec_helpers.rb +1 -1
- data/lib/stepford/version.rb +1 -1
- metadata +6 -4
data/README.md
CHANGED
@@ -1,32 +1,56 @@
|
|
1
1
|
Stepford
|
2
2
|
=====
|
3
3
|
|
4
|
-
|
4
|
+
Now getting started with FactoryGirl is even more simple and DRY!
|
5
5
|
|
6
|
-
|
6
|
+
Stepford is an automatic required (non-null or presence validated) association resolver and factory generator for [FactoryGirl][factory_girl].
|
7
7
|
|
8
|
-
|
8
|
+
The Stepford CLI allows can generate a factories.rb or multiple files each defining a single factory, for every existing model or for those specified.
|
9
9
|
|
10
|
-
|
10
|
+
The following would create/overwrite `test/factories.rb` with a factory for every model in `app/models`:
|
11
11
|
|
12
|
-
|
12
|
+
bundle exec stepford factories
|
13
|
+
|
14
|
+
If you use rspec, it would be:
|
15
|
+
|
16
|
+
bundle exec stepford factories --path spec
|
17
|
+
|
18
|
+
With our rspec helper, you can use this to create a bar and automatically create its dependencies and their dependencies, etc. providing ways to remedy circular dependencies:
|
19
|
+
|
20
|
+
deep_create(:bar)
|
13
21
|
|
14
|
-
|
22
|
+
You can also `create_list`, `build`, `build_list`, and `build_stubbed`:
|
15
23
|
|
16
|
-
|
24
|
+
deep_build_list(:bar, 5)
|
17
25
|
|
18
|
-
|
26
|
+
Need to customize it? You can use the normal FactoryGirl behavior (args, options, block), but in addition, you may specify options for each factories that would create direct or indirect associations.
|
27
|
+
|
28
|
+
e.g. maybe Bar has a required association called house_special which uses the beer factory, and we have a block we want to send into it, and Beer has specials that you want to build as a list of 3, using the tuesday_special_offer factory. In rspec, you'd do:
|
29
|
+
|
30
|
+
deep_create_list(:bar, with_factory_options: {
|
19
31
|
house_special: [:create, :beer, {blk: ->(beer) do; beer.bubbles.create(attributes_for(:bubbles)); end}],
|
20
32
|
specials: [:build_list, :tuesday_special_offer, 3]
|
21
33
|
}) do
|
22
34
|
# any block you would send to FactoryGirl.create_list(:bar) would go here
|
23
35
|
end
|
24
36
|
|
25
|
-
|
37
|
+
By default autogenerated factories just have required attributes, e.g.:
|
26
38
|
|
27
|
-
|
39
|
+
require 'factory_girl_rails'
|
40
|
+
|
41
|
+
FactoryGirl.define do
|
42
|
+
|
43
|
+
factory :post do
|
44
|
+
created_at { 2.weeks.ago }
|
45
|
+
name 'Test Name'
|
46
|
+
price 1.23
|
47
|
+
trait :with_summary do; template 'Test Summary'; end
|
48
|
+
updated_at { 2.weeks.ago }
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
28
52
|
|
29
|
-
|
53
|
+
But you can have it autogenerate lots of the FactoryGirl bells and whistles:
|
30
54
|
|
31
55
|
require 'factory_girl_rails'
|
32
56
|
|
@@ -48,6 +72,10 @@ e.g. maybe one of your models is called post, then you could generate a factory
|
|
48
72
|
|
49
73
|
end
|
50
74
|
|
75
|
+
But, everything from author to with_notes may have association interdependency issues unless you hand edit the generated versions.
|
76
|
+
|
77
|
+
Stepford's FactoryGirl (and optionally its rspec helper) can help you avoid the heavy lifting.
|
78
|
+
|
51
79
|
### Setup
|
52
80
|
|
53
81
|
In your Rails 3+ project, add this to your Gemfile:
|
@@ -95,9 +123,9 @@ Put this in your `spec/spec_helper.rb`:
|
|
95
123
|
|
96
124
|
require 'stepford/factory_girl_rspec_helpers'
|
97
125
|
|
98
|
-
Then you can just use `
|
126
|
+
Then you can just use `deep_create`, `deep_create_list`, `deep_build`, `deep_build_list`, or `deep_build_stubbed` in your rspec tests (`deep_create` becomes a shortcut for `::Stepford::FactoryGirl.create`, etc.), e.g.:
|
99
127
|
|
100
|
-
|
128
|
+
deep_create(:foo)
|
101
129
|
|
102
130
|
##### Stopping Circular References
|
103
131
|
|
@@ -108,6 +136,14 @@ If you have a circular reference (A has NOT NULL foreign key to B that has NOT N
|
|
108
136
|
[:waiter, :bar] => {on_loop: 2, set_to: Waiter.find(123)},
|
109
137
|
}
|
110
138
|
|
139
|
+
Leave out :on_loop or set :on_loop to 0 to use the set instead of attempting to build/create.
|
140
|
+
|
141
|
+
##### Debugging
|
142
|
+
|
143
|
+
Add somewhere after the require:
|
144
|
+
|
145
|
+
Stepford::FactoryGirl.debug = true
|
146
|
+
|
111
147
|
#### CLI
|
112
148
|
|
113
149
|
Stepford has a CLI with a circular reference checker and a generator to automatically create your factories file(s).
|
@@ -186,9 +222,9 @@ To generate traits for each association that would be included with `--associati
|
|
186
222
|
|
187
223
|
###### Associations
|
188
224
|
|
189
|
-
If you use
|
225
|
+
If you use Stepford::FactoryGirl (or deep_* methods in rspec) to automatically generate factories, you may not need to generate associations, because that sets them for you. If you do choose to use associations, note that these will likely create factories with interdependence issues. When there are NOT NULLs on foreign keys and/or presence validations, etc. you can't just use `after(:create)` or `after(:build)` to set associations, and without those you can have issues with "Trait not registered" or "Factory not registered". Later versions of FactoryGirl may make this easier, and be sure to see notes from Josh down in the troubleshooting section.
|
190
226
|
|
191
|
-
|
227
|
+
If you are ready to hand-edit to fix things, then copy paste stuff, rename it, etc. instead of just using Stepford::FactoryGirl (or deep_* methods in rspec), then keep reading.
|
192
228
|
|
193
229
|
####### Include Required Assocations
|
194
230
|
|
@@ -220,9 +256,39 @@ Currently uniqueness constraints are ignored and must be handled by FactoryGirl
|
|
220
256
|
|
221
257
|
sequence(:username) {|n| "user#{n}" }
|
222
258
|
|
223
|
-
|
259
|
+
##### Testing Factories
|
260
|
+
|
261
|
+
See [Testing all Factories (with RSpec)][test_factories] in the FactoryGirl wiki.
|
262
|
+
|
263
|
+
Here are a few rspecs that test the FactoryGirl factories and the Stepford deep_builds:
|
264
|
+
|
265
|
+
require 'spec_helper'
|
266
|
+
require 'stepford/factory_girl_rspec_helpers'
|
267
|
+
|
268
|
+
describe 'validate factories build' do
|
269
|
+
FactoryGirl.factories.each do |factory|
|
270
|
+
context "with factory for :#{factory.name}" do
|
271
|
+
subject { build(factory.name) }
|
272
|
+
|
273
|
+
it "is valid" do
|
274
|
+
subject.valid?.should be, subject.errors.full_messages
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
describe 'validate factories deep build' do
|
281
|
+
FactoryGirl.factories.each do |factory|
|
282
|
+
context "with factory for :#{factory.name}" do
|
283
|
+
subject { deep_build(factory.name) }
|
284
|
+
|
285
|
+
it "is valid" do
|
286
|
+
subject.valid?.should be, subject.errors.full_messages
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
224
291
|
|
225
|
-
See [Testing all Factories (with RSpec)][test_factories] in the FG wiki.
|
226
292
|
|
227
293
|
##### Troubleshooting
|
228
294
|
|
@@ -279,7 +345,13 @@ or referring to created objects through associations, though he said multiple ne
|
|
279
345
|
comment = FactoryGirl.create(:comment, :authored_by_post_author)
|
280
346
|
comment.author == comment.post.author # true
|
281
347
|
|
282
|
-
This is the reason we wrote the Stepford Factory Girl
|
348
|
+
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
|
+
|
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.
|
283
355
|
|
284
356
|
### License
|
285
357
|
|
@@ -67,19 +67,24 @@ module Stepford
|
|
67
67
|
|
68
68
|
def self.check_associations(model_class, model_and_association_names = [])
|
69
69
|
model_class.reflections.collect {|association_name, reflection|
|
70
|
-
next unless reflection.macro == :belongs_to
|
71
70
|
puts "warning: #{model_class}'s association #{reflection.name}'s foreign_key was nil. can't check." unless reflection.foreign_key
|
72
71
|
assc_sym = reflection.name.to_sym
|
73
72
|
clas_sym = reflection.class_name.underscore.to_sym
|
74
73
|
next_class = clas_sym.to_s.camelize.constantize
|
75
74
|
|
76
|
-
# 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
|
77
75
|
has_presence_validator = model_class.validators_on(assc_sym).collect{|v|v.class}.include?(ActiveModel::Validations::PresenceValidator)
|
78
|
-
|
79
|
-
|
80
|
-
|
76
|
+
required = false
|
77
|
+
if reflection.macro == :belongs_to
|
78
|
+
# note: supports composite_primary_keys gem which stores primary_key as an array
|
79
|
+
foreign_key_is_also_primary_key = Array.wrap(model_class.primary_key).collect{|pk|pk.to_sym}.include?(reflection.foreign_key.to_sym)
|
80
|
+
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}
|
81
|
+
required = is_not_null_fkey_that_is_not_primary_key || has_presence_validator
|
82
|
+
else
|
83
|
+
# 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
|
84
|
+
required = has_presence_validator
|
85
|
+
end
|
81
86
|
|
82
|
-
if
|
87
|
+
if required
|
83
88
|
key = [model_class.table_name.to_sym, reflection.foreign_key.to_sym, next_class.table_name.to_sym]
|
84
89
|
if model_and_association_names.include?(key)
|
85
90
|
@@offenders << model_and_association_names.last unless @@offenders.include?(model_and_association_names.last)
|
@@ -1,7 +1,8 @@
|
|
1
1
|
require 'factory_girl'
|
2
|
+
require 'bigdecimal'
|
2
3
|
|
3
4
|
module Stepford
|
4
|
-
# A
|
5
|
+
# A proxy for FactoryGirl that automatically recursively creates/builds/stubbed factories for null=false and/or presence validated associations.
|
5
6
|
#
|
6
7
|
# Lets you specify method name and arguments/options to factory girl for associations.
|
7
8
|
#
|
@@ -15,33 +16,24 @@ module Stepford
|
|
15
16
|
# }) do
|
16
17
|
# # the block you would send to FactoryGirl.create_list(:foo) would go here
|
17
18
|
# end
|
18
|
-
#
|
19
|
-
# If you have a circular reference (A has NOT NULL foreign key to B that has NOT NULL foreign key to C that has NOT NULL foreign key to A) in the
|
20
|
-
# schema, there is a workaround. First, prepopulate one of the models involved in the interdependency chain in the database as part of test setup,
|
21
|
-
# or if the ids are NOT NULL but are not foreign key constrained (i.e. if you can enter an invalid ID into the foreign key column, which implies possible
|
22
|
-
# referential integrity issues) then you may be able to set them with an invalid id. Take that foreign id and then use the following to ensure
|
23
|
-
# that it will set that foreign id or instance. This is done at a global level which may not work for you, but it makes it convenient to put into
|
24
|
-
# your spec/spec_helper.rb, etc. For example, let's say your bar has NOT NULL on bartender_id and waiter_id, and in turn bartender and waiter
|
25
|
-
# both have a NOT NULL bar_id, and neither enforce foreign keys. Maybe you have preloaded data for waiter somehow as the id '123', but want to set bartender to
|
26
|
-
# just use an invalid id '-1', and you want to do it when they are on their second loop. You could use:
|
27
|
-
#
|
28
|
-
# Stepford::FactoryGirl.stop_circular_refs = {
|
29
|
-
# [:bartender, :bar] => {on_loop: 2, set_foreign_key_to: -1},
|
30
|
-
# [:waiter, :bar] => {on_loop: 2, set_to: Waiter.find(123)},
|
31
|
-
# }
|
32
19
|
module FactoryGirl
|
33
20
|
OPTIONS = [
|
21
|
+
:debug,
|
34
22
|
:stop_circular_refs
|
35
23
|
]
|
36
24
|
|
37
25
|
class << self
|
26
|
+
@@breadcrumbs = []
|
27
|
+
|
38
28
|
OPTIONS.each{|o|attr_accessor o; define_method("#{o}?".to_sym){!!send("#{o}")}}
|
39
29
|
def configure(&blk); class_eval(&blk); end
|
40
30
|
|
41
|
-
def
|
42
|
-
|
31
|
+
def handle_factory_girl_method(m, *args, &block)
|
32
|
+
@@breadcrumbs << [args[0]] if ::Stepford::FactoryGirl.debug?
|
33
|
+
#puts "#{' ' * @@indent}handling Stepford::FactoryGirl.#{m}(#{args.inspect})" if ::Stepford::FactoryGirl.debug?
|
34
|
+
puts "#{@@breadcrumbs.join('>')} start" if ::Stepford::FactoryGirl.debug?
|
43
35
|
|
44
|
-
if
|
36
|
+
if args && args.size > 0
|
45
37
|
# call Stepford::FactoryGirl.* on any not null associations recursively
|
46
38
|
model_sym = args[0].to_sym
|
47
39
|
model_class = args[0].to_s.camelize.constantize
|
@@ -49,100 +41,68 @@ module Stepford
|
|
49
41
|
args = args.dup # need local version because we'll be dup'ing the options hash to add things to set prior to create/build
|
50
42
|
options = args.last
|
51
43
|
if options.is_a?(Hash)
|
52
|
-
|
44
|
+
# keep them separate
|
45
|
+
orig_options = options
|
46
|
+
options = deep_dup(options)
|
53
47
|
args[(args.size - 1)] = options # need to set the dup'd options
|
54
48
|
else
|
49
|
+
# keep them separate
|
50
|
+
orig_options = {}
|
55
51
|
options = {}
|
56
52
|
args << options # need to add options to set associations
|
57
53
|
end
|
58
54
|
|
55
|
+
if ::Stepford::FactoryGirl.debug?
|
56
|
+
print "#{@@breadcrumbs.join('>')} args="
|
57
|
+
debugargs(args)
|
58
|
+
puts
|
59
|
+
end
|
60
|
+
|
59
61
|
options[:with_factory_options] = {} unless options[:with_factory_options]
|
60
62
|
with_factory_options = options[:with_factory_options]
|
61
|
-
|
63
|
+
|
62
64
|
model_class.reflections.each do |association_name, reflection|
|
63
65
|
assc_sym = reflection.name.to_sym
|
64
|
-
next if options[assc_sym] || options[reflection.foreign_key.to_sym]
|
66
|
+
next if options[assc_sym] || options[reflection.foreign_key.to_sym] # || reflection.macro != :belongs_to
|
67
|
+
|
65
68
|
clas_sym = reflection.class_name.underscore.to_sym
|
66
69
|
has_presence_validator = model_class.validators_on(assc_sym).collect{|v|v.class}.include?(::ActiveModel::Validations::PresenceValidator)
|
67
70
|
required = reflection.foreign_key ? (has_presence_validator || model_class.columns.any?{|c| !c.null && c.name.to_sym == reflection.foreign_key.to_sym}) : false
|
68
71
|
orig_method_args_and_options = with_factory_options ? (with_factory_options[[clas_sym, assc_sym]] || with_factory_options[clas_sym]) : nil
|
69
|
-
|
72
|
+
|
70
73
|
has_presence_validator = model_class.validators_on(assc_sym).collect{|v|v.class}.include?(ActiveModel::Validations::PresenceValidator)
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
if
|
79
|
-
|
80
|
-
|
81
|
-
#puts "::Stepford::FactoryGirl.stop_circular_refs[circular_ref_key]=#{circ_options.inspect}"
|
82
|
-
count = with_factory_options[:circular_ref_counts][circular_ref_key]
|
83
|
-
if count
|
84
|
-
count += 1
|
85
|
-
else
|
86
|
-
count = 0
|
87
|
-
end
|
88
|
-
with_factory_options[:circular_ref_counts][circular_ref_key] = count
|
89
|
-
if count > 100
|
90
|
-
puts "over 100 loops. need to add this to Stepford::FactoryGirl.stop_circular_refs: {#{circular_ref_key.inspect} => {on_loop: 2, set_foreign_key_to: -1}}"
|
91
|
-
end
|
92
|
-
|
93
|
-
if count >= (circ_options[:on_loop] || 1)
|
94
|
-
if circ_options.has_key?(:set_to)
|
95
|
-
puts "Circular dependency override enabled. Returning :set_to instance to set as #{model_sym}.#{assc_sym}. instance was #{circ_options[:set_to]}"
|
96
|
-
return circ_options[:set_to]
|
97
|
-
elsif circ_options.has_key?(:set_foreign_key_to)
|
98
|
-
# (CHILD) return hash to set on parent
|
99
|
-
puts "Circular dependency override enabled. Returning :set_foreign_key_to to set as #{model_sym}.#{reflection.foreign_key}. value was '#{circ_options[:set_foreign_key_to]}'"
|
100
|
-
return {reflection.foreign_key.to_sym => circ_options[:set_foreign_key_to]}
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
74
|
+
required = false
|
75
|
+
if reflection.macro == :belongs_to
|
76
|
+
# note: supports composite_primary_keys gem which stores primary_key as an array
|
77
|
+
foreign_key_is_also_primary_key = Array.wrap(model_class.primary_key).collect{|pk|pk.to_sym}.include?(reflection.foreign_key.to_sym)
|
78
|
+
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}
|
79
|
+
required = is_not_null_fkey_that_is_not_primary_key || has_presence_validator
|
80
|
+
else
|
81
|
+
# 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
|
82
|
+
required = has_presence_validator
|
83
|
+
end
|
105
84
|
|
85
|
+
if required
|
86
|
+
@@breadcrumbs << ["a:#{assc_sym}"] if ::Stepford::FactoryGirl.debug?
|
106
87
|
if orig_method_args_and_options
|
107
88
|
method_args_and_options = orig_method_args_and_options.dup
|
108
89
|
method_options = args.last
|
109
90
|
blk = method_options.is_a?(Hash) ? method_args_and_options.delete(:blk) : nil
|
110
91
|
if blk
|
111
|
-
puts "FactoryGirl.__send__(#{method_args_and_options.inspect}, &blk)"
|
92
|
+
#puts "#{' ' * @@indent}FactoryGirl.__send__(#{method_args_and_options.inspect}, &blk)" if ::Stepford::FactoryGirl.debug?
|
112
93
|
options[assc_sym] = ::FactoryGirl.__send__(*method_args_and_options, &blk)
|
113
94
|
else
|
114
|
-
puts "FactoryGirl.__send__(#{method_args_and_options.inspect})"
|
95
|
+
#puts "#{' ' * @@indent}FactoryGirl.__send__(#{method_args_and_options.inspect})" if ::Stepford::FactoryGirl.debug?
|
115
96
|
options[assc_sym] = ::FactoryGirl.__send__(*method_args_and_options)
|
116
97
|
end
|
117
98
|
else
|
118
99
|
if reflection.macro == :has_many
|
119
|
-
|
120
|
-
when :create, :create_list
|
121
|
-
options[assc_sym] = ::Stepford::FactoryGirl.create_list(clas_sym, 2, options)
|
122
|
-
when :build, :build_list
|
123
|
-
options[assc_sym] = ::Stepford::FactoryGirl.build_list(clas_sym, 2, options)
|
124
|
-
when :build_stubbed
|
125
|
-
#TODO: need to test building something stubbed that has a PresenceValidator on a has_many
|
126
|
-
options[assc_sym] = ::Stepford::FactoryGirl.build_stubbed(clas_sym, options)
|
127
|
-
end
|
100
|
+
options[assc_sym] = ::Stepford::FactoryGirl.create_list(clas_sym, 2, orig_options)
|
128
101
|
else
|
129
|
-
|
130
|
-
when :create, :create_list
|
131
|
-
options[assc_sym] = ::Stepford::FactoryGirl.create(clas_sym, options)
|
132
|
-
when :build, :build_list
|
133
|
-
options[assc_sym] = ::Stepford::FactoryGirl.build(clas_sym, options)
|
134
|
-
when :build_stubbed
|
135
|
-
options[assc_sym] = ::Stepford::FactoryGirl.build_stubbed(clas_sym, options)
|
136
|
-
end
|
137
|
-
|
138
|
-
# (PARENT) we passed this back as a hash which means that the child model needed to set foreign key on the parent model
|
139
|
-
if options[assc_sym].is_a?(Hash)
|
140
|
-
value = options.delete(assc_sym)
|
141
|
-
options.merge!()
|
142
|
-
puts "Overrode foreign key #{model_sym}.#{assc_sym} = #{value}"
|
143
|
-
end
|
102
|
+
options[assc_sym] = ::Stepford::FactoryGirl.create(clas_sym, orig_options)
|
144
103
|
end
|
145
104
|
end
|
105
|
+
@@breadcrumbs.pop if ::Stepford::FactoryGirl.debug?
|
146
106
|
end
|
147
107
|
end
|
148
108
|
end
|
@@ -150,9 +110,69 @@ module Stepford
|
|
150
110
|
# clean-up before sending to FactoryGirl
|
151
111
|
(args.last).delete(:with_factory_options) if args.last.is_a?(Hash)
|
152
112
|
|
153
|
-
|
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
|
121
|
+
end
|
122
|
+
|
154
123
|
::FactoryGirl.__send__(m, *args, &block)
|
155
124
|
end
|
125
|
+
|
126
|
+
# switched to this from method_missing to avoid method trying to handle mistaken calls
|
127
|
+
def create(*args, &block); handle_factory_girl_method(:create, *args, &block); end
|
128
|
+
def create_list(*args, &block); handle_factory_girl_method(:create_list, *args, &block); end
|
129
|
+
def build(*args, &block); handle_factory_girl_method(:build, *args, &block); end
|
130
|
+
def build_list(*args, &block); handle_factory_girl_method(:build_list, *args, &block); end
|
131
|
+
def build_stubbed(*args, &block); handle_factory_girl_method(:build_stubbed, *args, &block); end
|
132
|
+
# pass everything else to FactoryGirl to try to handle (can't reflect in current version to find what it handles)
|
133
|
+
def method_missing(m, *args, &block); ::FactoryGirl.__send__(m, *args, &block); end
|
134
|
+
|
135
|
+
def deep_dup(o)
|
136
|
+
result = nil
|
137
|
+
if o.is_a?(Hash)
|
138
|
+
result = {}
|
139
|
+
o.keys.each do |key|
|
140
|
+
result[deep_dup(key)] = deep_dup(o[key])
|
141
|
+
end
|
142
|
+
elsif o.is_a?(Array)
|
143
|
+
result = []
|
144
|
+
o.each do |value|
|
145
|
+
result << deep_dup(value)
|
146
|
+
end
|
147
|
+
elsif [NilClass,FalseClass,TrueClass,Symbol,Numeric,Class,Module].any?{|c|o.is_a?(c)}
|
148
|
+
result = o
|
149
|
+
elsif o.is_a?(BigDecimal)
|
150
|
+
# ActiveSupport v3.2.8 checks duplicable? for BigDecimal by testing it, so we'll just try to dup the value itself
|
151
|
+
result = o
|
152
|
+
begin
|
153
|
+
result = o.dup
|
154
|
+
rescue TypeError
|
155
|
+
# can't dup
|
156
|
+
end
|
157
|
+
elsif o.is_a?(Object)
|
158
|
+
result = o.dup
|
159
|
+
else
|
160
|
+
result = o
|
161
|
+
end
|
162
|
+
result
|
163
|
+
end
|
164
|
+
|
165
|
+
def debugargs(args)
|
166
|
+
args.each do |arg|
|
167
|
+
if arg.is_a?(Hash)
|
168
|
+
print "{"
|
169
|
+
print arg.keys.collect{|key|"#{key} = (#{arg[key].class.name})"}.join(', ')
|
170
|
+
print "}"
|
171
|
+
else
|
172
|
+
print "#{arg.inspect},"
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
156
176
|
end
|
157
177
|
end
|
158
178
|
end
|
data/lib/stepford/version.rb
CHANGED
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.
|
4
|
+
version: 0.11.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-11-
|
12
|
+
date: 2012-11-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: thor
|
@@ -43,7 +43,9 @@ dependencies:
|
|
43
43
|
- - ! '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: '0'
|
46
|
-
description:
|
46
|
+
description: Has deep_* methods for automating FactoryGirl creation with required
|
47
|
+
association trees and small tweaks, ActiveRecord circular required reference checker
|
48
|
+
CLI, and a nice flexible FactoryGirl factories code generator CLI.
|
47
49
|
email:
|
48
50
|
- garysweaver@gmail.com
|
49
51
|
executables:
|
@@ -86,5 +88,5 @@ rubyforge_project:
|
|
86
88
|
rubygems_version: 1.8.24
|
87
89
|
signing_key:
|
88
90
|
specification_version: 3
|
89
|
-
summary:
|
91
|
+
summary: FactoryGirl becomes easier and automated.
|
90
92
|
test_files: []
|