stepford 0.9.1 → 0.9.2

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 CHANGED
@@ -125,6 +125,36 @@ Check ActiveRecord circular dependencies:
125
125
 
126
126
  bundle exec stepford circular
127
127
 
128
+ Then it outputs the circular dependencies, e.g.:
129
+
130
+ The following non-nullable foreign keys used in ActiveRecord model associations are involved in circular dependencies:
131
+
132
+ foo.bar_id -> bar.bartender_id -> bartender.sandwich_id -> sandwich.foo_id
133
+
134
+ foo.bar_id -> bar.waiter_id -> waiter.waitress_id
135
+
136
+ waitress.waiter_id -> bar.waiter_id -> waiter.waitress_id
137
+
138
+ ...
139
+
140
+ Distinct foreign keys involved in a circular dependency:
141
+
142
+ bar.bartender_id
143
+ bar.waiter_id
144
+ bartender.sandwich_id
145
+ foo.bar_id
146
+ sandwich.foo_id
147
+ waiter.waitress_id
148
+ waitress.waiter_id
149
+
150
+ Foreign keys by number of circular dependency chains involved with:
151
+
152
+ 3 (out of 6): bar.bartender_id -> bartender
153
+ 2 (out of 6): bar.waiter_id -> waiter
154
+ 1 (out of 6): bartender.sandwich_id -> sandwich
155
+ 1 (out of 6): foo.bar_id -> bar
156
+ ...
157
+
128
158
  ##### Factories
129
159
 
130
160
  ###### Creating Factories
@@ -26,24 +26,34 @@ module Stepford
26
26
  check_associations(model_class)
27
27
  end
28
28
 
29
- puts "Circles of shame:"
29
+ puts "The following non-nullable foreign keys used in ActiveRecord model associations are involved in circular dependencies:"
30
30
  @@circles.sort.each do |c|
31
31
  puts
32
32
  puts "#{c}"
33
33
  end
34
34
  puts
35
35
  puts
36
- puts "All foreign keys involved in a circular dependency:"
36
+ puts "Distinct foreign keys involved in a circular dependency:"
37
37
  puts
38
38
  @@offenders.sort.each do |c|
39
39
  puts "#{c[0]}.#{c[1]}"
40
40
  end
41
+
42
+ totals = {}
43
+ @@circles_sorted.each do |arr|
44
+ arr.each do |key|
45
+ totals[key] = 0 unless totals[key]
46
+ totals[key] = totals[key] + 1
47
+ end
48
+ end
41
49
  puts
42
50
  puts
43
- puts "Arbitrarily chosen foreign_keys involved in a circular dependency that would break each circular dependency chain if marked as nullable. It would be a better idea to examine the full list of foreign keys and circles above, fix, then rerun:"
51
+ puts "Foreign keys by number of circular dependency chains involved with:"
44
52
  puts
45
- @@selected_offenders.sort.each do |c|
46
- puts "#{c[0]}.#{c[1]}"
53
+ totals.sort_by {|k,v| v}.reverse.each do |arr|
54
+ c = arr[0]
55
+ t = arr[1]
56
+ puts "#{t} (out of #{@@circles_sorted.size}): #{c[0]}.#{c[1]} -> #{c[2]}"
47
57
  end
48
58
 
49
59
  return (@@offenders.size == 0)
@@ -51,18 +61,19 @@ module Stepford
51
61
 
52
62
  def self.check_associations(model_class)
53
63
  @@level += 1
54
-
64
+
55
65
  model_class.reflections.collect {|association_name, reflection|
56
66
  @@model_and_association_names = [] if @@level == 1
57
67
  next unless reflection.macro == :belongs_to
58
68
  assc_sym = reflection.name.to_sym
59
69
  clas_sym = reflection.class_name.underscore.to_sym
70
+ next_class = clas_sym.to_s.camelize.constantize
60
71
 
61
72
  # 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
62
73
  has_presence_validator = model_class.validators_on(assc_sym).collect{|v|v.class}.include?(ActiveModel::Validations::PresenceValidator)
63
74
  required = reflection.foreign_key ? (has_presence_validator || model_class.columns.any?{|c| !c.null && c.name.to_sym == reflection.foreign_key.to_sym}) : false
64
75
  if required
65
- key = [model_class.to_s.underscore.to_sym, assc_sym]
76
+ key = [model_class.table_name.to_sym, reflection.foreign_key.to_sym, next_class.table_name]
66
77
  if @@model_and_association_names.include?(key)
67
78
  @@offenders << @@model_and_association_names.last unless @@offenders.include?(@@model_and_association_names.last)
68
79
  short = @@model_and_association_names.dup
@@ -71,13 +82,11 @@ module Stepford
71
82
  sorted = short.sort
72
83
  unless @@circles_sorted.include?(sorted)
73
84
  @@circles_sorted << sorted
74
- last_key_in_circle_before_restart = short.last
75
- @@selected_offenders << last_key_in_circle_before_restart unless @@selected_offenders.include?(last_key_in_circle_before_restart)
76
85
  @@circles << "#{(short << key).collect{|b|"#{b[0]}.#{b[1]}"}.join(' -> ')}".to_sym
77
86
  end
78
87
  else
79
88
  @@model_and_association_names << key
80
- check_associations(reflection.class_name.constantize)
89
+ check_associations(next_class)
81
90
  end
82
91
  end
83
92
  }
@@ -1,3 +1,3 @@
1
1
  module Stepford
2
- VERSION = '0.9.1'
2
+ VERSION = '0.9.2'
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.9.1
4
+ version: 0.9.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors: