stepford 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +47 -10
- data/lib/stepford/cli.rb +2 -0
- data/lib/stepford/factory_girl.rb +28 -38
- data/lib/stepford/version.rb +1 -1
- metadata +1 -1
data/README.md
CHANGED
|
@@ -7,14 +7,10 @@ Stepford is a CLI to create starter [Factory Girl][factory_girl] factories for a
|
|
|
7
7
|
|
|
8
8
|
FactoryGirl.define do
|
|
9
9
|
|
|
10
|
-
factory :
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
association :created_by, factory: :user
|
|
15
|
-
after(:create) do |item, evaluator|
|
|
16
|
-
FactoryGirl.create_list :subparts, evaluator.subpart_count, item: item
|
|
17
|
-
end
|
|
10
|
+
factory :post do
|
|
11
|
+
author
|
|
12
|
+
association :edited_by, factory: :user
|
|
13
|
+
FactoryGirl.create_list :comments, 2
|
|
18
14
|
created_at { 2.weeks.ago }
|
|
19
15
|
name 'Test Name'
|
|
20
16
|
price 1.23
|
|
@@ -41,7 +37,7 @@ Then run:
|
|
|
41
37
|
|
|
42
38
|
#### Factory Girl
|
|
43
39
|
|
|
44
|
-
The default will assume a `test/factories` directory exists and that it should create a factory file for each model:
|
|
40
|
+
The default will assume a `test/factories` directory exists and that it should create a factory file for each model with non-primary key, non-foreign key attributes only, and no associations:
|
|
45
41
|
|
|
46
42
|
bundle exec stepford factories
|
|
47
43
|
|
|
@@ -53,9 +49,15 @@ It will figure out that you want a single file, if the path ends in `.rb`:
|
|
|
53
49
|
|
|
54
50
|
bundle exec stepford factories --path spec/support/factories.rb
|
|
55
51
|
|
|
52
|
+
### Associations
|
|
53
|
+
|
|
54
|
+
To include associations:
|
|
55
|
+
|
|
56
|
+
bundle exec stepford factories --associations
|
|
57
|
+
|
|
56
58
|
### Stepford Checks Model Associations
|
|
57
59
|
|
|
58
|
-
Stepford first loads Rails and attempts to check your models for broken associations.
|
|
60
|
+
If `--associations` or `--validate_associations` is specified, Stepford first loads Rails and attempts to check your models for broken associations.
|
|
59
61
|
|
|
60
62
|
If associations are deemed broken, it will output proposed changes.
|
|
61
63
|
|
|
@@ -67,6 +69,41 @@ Uses the Ruby 1.9 hash syntax in generated factories. If you don't have 1.9, it
|
|
|
67
69
|
|
|
68
70
|
If you are using STI, you'll need to manually fix the value that goes into the `type` attribute, or remove it.
|
|
69
71
|
|
|
72
|
+
If you specify `--associations`, you might run into issue with circular associations, so you could easily end up with:
|
|
73
|
+
|
|
74
|
+
SystemStackError:
|
|
75
|
+
stack level too deep
|
|
76
|
+
|
|
77
|
+
Some suggestions from ThoughtBot's Josh Clayton provided include using methods to generate more complex object structures:
|
|
78
|
+
|
|
79
|
+
def post_containing_comment_by_author
|
|
80
|
+
author = FactoryGirl.create(:user)
|
|
81
|
+
post = FactoryGirl.create(:post)
|
|
82
|
+
FactoryGirl.create_list(:comment, 3)
|
|
83
|
+
FactoryGirl.create(:comment, author: author, post: post)
|
|
84
|
+
post.reload
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
or referring to created objects through associations, though he said multiple nestings get tricky:
|
|
88
|
+
|
|
89
|
+
factory :post do
|
|
90
|
+
author
|
|
91
|
+
title 'Ruby is fun'
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
factory :comment do
|
|
95
|
+
author
|
|
96
|
+
post
|
|
97
|
+
body 'I love Ruby too!'
|
|
98
|
+
|
|
99
|
+
trait :authored_by_post_author do
|
|
100
|
+
author { post.author }
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
comment = FactoryGirl.create(:comment, :authored_by_post_author)
|
|
105
|
+
comment.author == comment.post.author # true
|
|
106
|
+
|
|
70
107
|
### License
|
|
71
108
|
|
|
72
109
|
Copyright (c) 2012 Gary S. Weaver, released under the [MIT license][lic].
|
data/lib/stepford/cli.rb
CHANGED
|
@@ -5,6 +5,8 @@ module Stepford
|
|
|
5
5
|
desc "factories", "create FactoryGirl factories"
|
|
6
6
|
method_option :single, :desc => "Put all factories into a single file"
|
|
7
7
|
method_option :path, :desc => "Pathname of file to contain factories or path of directory to contain factory/factories"
|
|
8
|
+
method_option :associations, :desc => "Include associations in factories"
|
|
9
|
+
method_option :validate_associations, :desc => "Validate associations in factories even if not including associations"
|
|
8
10
|
def factories()
|
|
9
11
|
# load Rails environment
|
|
10
12
|
require './config/environment'
|
|
@@ -14,58 +14,48 @@ module Stepford
|
|
|
14
14
|
factory = (factories[model_name.to_sym] ||= [])
|
|
15
15
|
primary_keys = Array.wrap(model_class.primary_key).collect{|pk|pk.to_sym}
|
|
16
16
|
foreign_keys = []
|
|
17
|
-
ignored = []
|
|
18
|
-
after_create = []
|
|
19
17
|
association_lines = model_class.reflections.collect {|association_name, reflection|
|
|
20
18
|
(expected[reflection.class_name.underscore.to_sym] ||= []) << model_name
|
|
21
19
|
foreign_keys << reflection.foreign_key.to_sym
|
|
22
20
|
assc_sym = reflection.name.to_sym
|
|
23
21
|
clas_sym = reflection.class_name.underscore.to_sym
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
# we have to do the part above to not set arbitrary values in foreign key attributes
|
|
23
|
+
if options[:associations]
|
|
24
|
+
if reflection.macro == :has_many
|
|
25
|
+
"FactoryGirl.create_list #{assc_sym.inspect}, 2"
|
|
26
|
+
elsif assc_sym != clas_sym
|
|
27
|
+
"association #{assc_sym.inspect}#{assc_sym != clas_sym ? ", factory: #{clas_sym.inspect}" : ''}"
|
|
28
|
+
else
|
|
29
|
+
"#{assc_sym}"
|
|
30
|
+
end
|
|
28
31
|
else
|
|
29
|
-
|
|
30
|
-
end
|
|
31
|
-
}.compact.sort
|
|
32
|
-
if ignored.size > 0
|
|
33
|
-
factory << 'ignore do'
|
|
34
|
-
ignored.each do |name|
|
|
35
|
-
factory << " #{name}_count 2"
|
|
36
|
-
end
|
|
37
|
-
factory << 'end'
|
|
38
|
-
end
|
|
39
|
-
association_lines.each {|l|factory << l}
|
|
40
|
-
if after_create.size > 0
|
|
41
|
-
factory << "after(:create) do |#{model_name}, evaluator|"
|
|
42
|
-
after_create.each do |line|
|
|
43
|
-
factory << " #{line}"
|
|
32
|
+
nil
|
|
44
33
|
end
|
|
45
|
-
|
|
46
|
-
end
|
|
34
|
+
}.compact.sort.each {|l|factory << l}
|
|
47
35
|
model_class.columns.collect {|c| "#{c.name.to_sym} #{Stepford::Common.value_for(c.name, c.type)}" unless foreign_keys.include?(c.name.to_sym) || primary_keys.include?(c.name.to_sym)}.compact.sort.each {|l|factory << l}
|
|
48
36
|
end
|
|
49
37
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
38
|
+
if options[:associations] || options[:validate_associations]
|
|
39
|
+
failed = false
|
|
40
|
+
model_to_fixes_required = {}
|
|
41
|
+
expected.keys.sort.each do |factory_name|
|
|
42
|
+
unless factories[factory_name.to_sym]
|
|
43
|
+
puts "#{File.join('app','models',"#{factory_name}.rb")} missing. Model(s) with associations to it: #{expected[factory_name].sort.join(', ')}"
|
|
44
|
+
expected[factory_name].each do |model_name|
|
|
45
|
+
(model_to_fixes_required[model_name.to_sym] ||= []) << factory_name.to_sym
|
|
46
|
+
end
|
|
47
|
+
failed = true
|
|
57
48
|
end
|
|
58
|
-
failed = true
|
|
59
49
|
end
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
50
|
+
model_to_fixes_required.keys.each do |model_to_fix|
|
|
51
|
+
puts ""
|
|
52
|
+
puts "In #{model_to_fix}:"
|
|
53
|
+
model_to_fixes_required[model_to_fix].each do |fix|
|
|
54
|
+
puts "- comment/remove/fix broken association to #{fix}"
|
|
55
|
+
end
|
|
66
56
|
end
|
|
57
|
+
return false if failed
|
|
67
58
|
end
|
|
68
|
-
return false if failed
|
|
69
59
|
|
|
70
60
|
path = File.join('test','factories.rb')
|
|
71
61
|
if options[:path]
|
data/lib/stepford/version.rb
CHANGED