stepford 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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 :item do
11
- ignore do
12
- subpart_count 2
13
- end
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
- if reflection.macro == :has_many
25
- ignored << clas_sym
26
- after_create << "FactoryGirl.create_list #{assc_sym.inspect}, evaluator.#{clas_sym}_count, #{model_name}: #{model_name}"
27
- nil
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
- "association #{assc_sym.inspect}#{assc_sym != clas_sym ? ", factory: #{clas_sym.inspect}" : ''}"
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
- factory << 'end'
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
- failed = false
51
- model_to_fixes_required = {}
52
- expected.keys.sort.each do |factory_name|
53
- unless factories[factory_name.to_sym]
54
- puts "#{File.join('app','models',"#{factory_name}.rb")} missing. Model(s) with associations to it: #{expected[factory_name].sort.join(', ')}"
55
- expected[factory_name].each do |model_name|
56
- (model_to_fixes_required[model_name.to_sym] ||= []) << factory_name.to_sym
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
- end
61
- model_to_fixes_required.keys.each do |model_to_fix|
62
- puts ""
63
- puts "In #{model_to_fix}:"
64
- model_to_fixes_required[model_to_fix].each do |fix|
65
- puts "- comment/remove/fix broken association to #{fix}"
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]
@@ -1,3 +1,3 @@
1
1
  module Stepford
2
- VERSION = '0.1.0'
2
+ VERSION = '0.2.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.1.0
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors: