rails_best_practices 0.5.0 → 0.5.1
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.
@@ -5,11 +5,11 @@ module RailsBestPractices
|
|
5
5
|
module Checks
|
6
6
|
# Check db/schema.rb file to make sure every reference key has a database index.
|
7
7
|
#
|
8
|
-
# Implementation: read all add_index method calls to get the indexed columns in table, then read integer method call in create_table block to get the reference columns in tables, compare with indexed columns, if not in the indexed columns, then it violates always_add_db_index_check.
|
8
|
+
# Implementation: read all add_index method calls to get the indexed columns in table, then read integer method call in create_table block to get the reference columns in tables (or polymorphic index like [commentable_id, commentable_type]), compare with indexed columns, if not in the indexed columns, then it violates always_add_db_index_check.
|
9
9
|
class AlwaysAddDbIndexCheck < Check
|
10
10
|
|
11
11
|
def interesting_nodes
|
12
|
-
[:block, :call]
|
12
|
+
[:block, :call, :iter]
|
13
13
|
end
|
14
14
|
|
15
15
|
def interesting_files
|
@@ -18,7 +18,9 @@ module RailsBestPractices
|
|
18
18
|
|
19
19
|
def initialize
|
20
20
|
super
|
21
|
-
@index_columns =
|
21
|
+
@index_columns = {}
|
22
|
+
@foreign_keys = {}
|
23
|
+
@table_nodes = {}
|
22
24
|
end
|
23
25
|
|
24
26
|
def evaluate_start(node)
|
@@ -28,27 +30,48 @@ module RailsBestPractices
|
|
28
30
|
case node.message
|
29
31
|
when :create_table
|
30
32
|
@table_name = node.arguments[1].to_s
|
31
|
-
|
33
|
+
@table_nodes[@table_name] = node
|
34
|
+
when :integer, :string
|
32
35
|
column_name = node.arguments[1].to_s
|
33
|
-
|
34
|
-
|
36
|
+
add_foreign_key_column(@table_name, column_name)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def evaluate_end(node)
|
42
|
+
if :iter == node.node_type && :call == node.subject.node_type && s(:colon2, s(:const, :ActiveRecord), :Schema) == node.subject.subject
|
43
|
+
@foreign_keys.each do |table, foreign_key|
|
44
|
+
table_node = @table_nodes[table]
|
45
|
+
foreign_key.each do |column|
|
46
|
+
unless @index_columns[table] && @index_columns[table].include?(column)
|
47
|
+
add_error "always add db index (#{table} => [#{Array(column).join(', ')}])", table_node.file, table_node.line
|
48
|
+
end
|
35
49
|
end
|
36
50
|
end
|
37
51
|
end
|
38
52
|
end
|
39
|
-
|
53
|
+
|
40
54
|
private
|
41
55
|
def find_index_columns(node)
|
42
56
|
node.grep_nodes({:node_type => :call, :message => :add_index}).each do |index_node|
|
43
57
|
table_name = index_node.arguments[1].to_s
|
44
|
-
|
45
|
-
|
58
|
+
index_column = eval(index_node.arguments[2].to_s)
|
59
|
+
add_index_column(table_name, index_column)
|
46
60
|
end
|
47
61
|
end
|
48
|
-
|
49
|
-
def
|
50
|
-
|
51
|
-
|
62
|
+
|
63
|
+
def add_index_column(table_name, index_column)
|
64
|
+
@index_columns[table_name] ||= []
|
65
|
+
@index_columns[table_name] << (index_column.size == 1 ? index_column[0] : index_column)
|
66
|
+
end
|
67
|
+
|
68
|
+
def add_foreign_key_column(table_name, foreign_key_column)
|
69
|
+
if foreign_key_column =~ /_id$/
|
70
|
+
@foreign_keys[table_name] ||= []
|
71
|
+
@foreign_keys[table_name] << foreign_key_column
|
72
|
+
elsif foreign_key_column =~ /(.*?)_type$/
|
73
|
+
@foreign_keys[table_name].delete("#{$1}_id")
|
74
|
+
@foreign_keys[table_name] << ["#{$1}_id", foreign_key_column]
|
52
75
|
end
|
53
76
|
end
|
54
77
|
end
|
@@ -6,7 +6,7 @@ require 'colored'
|
|
6
6
|
options = {}
|
7
7
|
OptionParser.new do |opts|
|
8
8
|
opts.banner = "Usage: rails_best_practices [options]"
|
9
|
-
|
9
|
+
|
10
10
|
opts.on("-d", "--debug", "Debug mode") do
|
11
11
|
options['debug'] = true
|
12
12
|
end
|
@@ -16,7 +16,7 @@ OptionParser.new do |opts|
|
|
16
16
|
options[pattern] = true
|
17
17
|
end
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
opts.on_tail('-v', '--version', 'Show this version') do
|
21
21
|
require 'rails_best_practices/version'
|
22
22
|
puts RailsBestPractices::VERSION
|
@@ -27,7 +27,7 @@ OptionParser.new do |opts|
|
|
27
27
|
puts opts
|
28
28
|
exit
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
opts.on("-x", "--exclude PATTERNS", "Don't analyze files matching a pattern", "(comma-separated regexp list)") do |list|
|
32
32
|
begin
|
33
33
|
options[:exclude] = list.split(/,/).map{|x| Regexp.new x}
|
@@ -43,6 +43,12 @@ runner = RailsBestPractices::Core::Runner.new
|
|
43
43
|
runner.set_debug if options['debug']
|
44
44
|
|
45
45
|
files = RailsBestPractices::analyze_files(ARGV, options)
|
46
|
+
|
47
|
+
if runner.checks.find { |check| check.is_a? RailsBestPractices::Checks::AlwaysAddDbIndexCheck } &&
|
48
|
+
!files.find { |file| file.index "db\/schema.rb" }
|
49
|
+
puts "AlwaysAddDbIndexCheck is disabled as there is no db/schema.rb file in your rails project.".blue
|
50
|
+
end
|
51
|
+
|
46
52
|
bar = ProgressBar.new('Analyzing', files.size)
|
47
53
|
files.each do |file|
|
48
54
|
runner.check_file(file)
|
@@ -50,9 +56,11 @@ files.each do |file|
|
|
50
56
|
end
|
51
57
|
bar.finish
|
52
58
|
|
53
|
-
runner.errors.each {|error| puts error.to_s.red}
|
59
|
+
runner.errors.each { |error| puts error.to_s.red }
|
54
60
|
puts "\nPlease go to http://rails-bestpractices.com to see more useful Rails Best Practices.".green
|
55
|
-
if runner.errors.
|
61
|
+
if runner.errors.empty?
|
62
|
+
puts "\nNo error found. Cool!".green
|
63
|
+
else
|
56
64
|
puts "\nFound #{runner.errors.size} errors.".red
|
57
65
|
end
|
58
66
|
|
@@ -8,9 +8,11 @@ require 'active_support/inflector'
|
|
8
8
|
module RailsBestPractices
|
9
9
|
module Core
|
10
10
|
class Runner
|
11
|
+
attr_reader :checks
|
12
|
+
|
11
13
|
DEFAULT_CONFIG = File.join(File.dirname(__FILE__), "..", "..", "..", "rails_best_practices.yml")
|
12
14
|
CUSTOM_CONFIG = File.join('config', 'rails_best_practices.yml')
|
13
|
-
|
15
|
+
|
14
16
|
def initialize(*checks)
|
15
17
|
@config = File.exists?(CUSTOM_CONFIG) ? CUSTOM_CONFIG : DEFAULT_CONFIG
|
16
18
|
@checks = checks unless checks.empty?
|
@@ -18,7 +20,7 @@ module RailsBestPractices
|
|
18
20
|
@checker ||= CheckingVisitor.new(@checks)
|
19
21
|
@debug = false
|
20
22
|
end
|
21
|
-
|
23
|
+
|
22
24
|
def set_debug
|
23
25
|
@debug = true
|
24
26
|
end
|
@@ -67,11 +69,11 @@ module RailsBestPractices
|
|
67
69
|
nil
|
68
70
|
end
|
69
71
|
end
|
70
|
-
|
72
|
+
|
71
73
|
def load_checks
|
72
74
|
check_objects = []
|
73
75
|
checks = YAML.load_file @config
|
74
|
-
checks.each do |check|
|
76
|
+
checks.each do |check|
|
75
77
|
klass = eval("RailsBestPractices::Checks::#{check[0]}")
|
76
78
|
check_objects << (check[1].empty? ? klass.new : klass.new(check[1]))
|
77
79
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails_best_practices
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 9
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 5
|
9
|
-
-
|
10
|
-
version: 0.5.
|
9
|
+
- 1
|
10
|
+
version: 0.5.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Richard Huang
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-
|
18
|
+
date: 2010-12-01 00:00:00 +08:00
|
19
19
|
default_executable: rails_best_practices
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -75,12 +75,26 @@ dependencies:
|
|
75
75
|
segments:
|
76
76
|
- 0
|
77
77
|
version: "0"
|
78
|
-
name:
|
78
|
+
name: i18n
|
79
79
|
prerelease: false
|
80
80
|
type: :runtime
|
81
81
|
version_requirements: *id004
|
82
82
|
- !ruby/object:Gem::Dependency
|
83
83
|
requirement: &id005 !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
hash: 3
|
89
|
+
segments:
|
90
|
+
- 0
|
91
|
+
version: "0"
|
92
|
+
name: activesupport
|
93
|
+
prerelease: false
|
94
|
+
type: :runtime
|
95
|
+
version_requirements: *id005
|
96
|
+
- !ruby/object:Gem::Dependency
|
97
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
84
98
|
none: false
|
85
99
|
requirements:
|
86
100
|
- - ~>
|
@@ -94,9 +108,9 @@ dependencies:
|
|
94
108
|
name: rspec
|
95
109
|
prerelease: false
|
96
110
|
type: :development
|
97
|
-
version_requirements: *
|
111
|
+
version_requirements: *id006
|
98
112
|
- !ruby/object:Gem::Dependency
|
99
|
-
requirement: &
|
113
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
100
114
|
none: false
|
101
115
|
requirements:
|
102
116
|
- - ~>
|
@@ -110,9 +124,9 @@ dependencies:
|
|
110
124
|
name: haml
|
111
125
|
prerelease: false
|
112
126
|
type: :development
|
113
|
-
version_requirements: *
|
127
|
+
version_requirements: *id007
|
114
128
|
- !ruby/object:Gem::Dependency
|
115
|
-
requirement: &
|
129
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
116
130
|
none: false
|
117
131
|
requirements:
|
118
132
|
- - ~>
|
@@ -125,7 +139,7 @@ dependencies:
|
|
125
139
|
name: watchr
|
126
140
|
prerelease: false
|
127
141
|
type: :development
|
128
|
-
version_requirements: *
|
142
|
+
version_requirements: *id008
|
129
143
|
description: a code metric tool for rails codes, written in Ruby.
|
130
144
|
email:
|
131
145
|
- flyerhzm@gmail.com
|
@@ -137,39 +151,39 @@ extra_rdoc_files:
|
|
137
151
|
- MIT_LICENSE
|
138
152
|
- README.textile
|
139
153
|
files:
|
140
|
-
- lib/rails_best_practices.rb
|
141
|
-
- lib/rails_best_practices/version.rb
|
142
|
-
- lib/rails_best_practices/checks/move_finder_to_named_scope_check.rb
|
143
|
-
- lib/rails_best_practices/checks/use_model_association_check.rb
|
144
|
-
- lib/rails_best_practices/checks/keep_finders_on_their_own_model_check.rb
|
145
154
|
- lib/rails_best_practices/checks/add_model_virtual_attribute_check.rb
|
146
|
-
- lib/rails_best_practices/checks/
|
155
|
+
- lib/rails_best_practices/checks/always_add_db_index_check.rb
|
156
|
+
- lib/rails_best_practices/checks/check.rb
|
157
|
+
- lib/rails_best_practices/checks/dry_bundler_in_capistrano_check.rb
|
158
|
+
- lib/rails_best_practices/checks/isolate_seed_data_check.rb
|
159
|
+
- lib/rails_best_practices/checks/keep_finders_on_their_own_model_check.rb
|
147
160
|
- lib/rails_best_practices/checks/law_of_demeter_check.rb
|
148
|
-
- lib/rails_best_practices/checks/use_scope_access_check.rb
|
149
161
|
- lib/rails_best_practices/checks/move_code_into_controller_check.rb
|
162
|
+
- lib/rails_best_practices/checks/move_code_into_helper_check.rb
|
163
|
+
- lib/rails_best_practices/checks/move_code_into_model_check.rb
|
164
|
+
- lib/rails_best_practices/checks/move_finder_to_named_scope_check.rb
|
150
165
|
- lib/rails_best_practices/checks/move_model_logic_into_model_check.rb
|
166
|
+
- lib/rails_best_practices/checks/needless_deep_nesting_check.rb
|
151
167
|
- lib/rails_best_practices/checks/not_use_default_route_check.rb
|
168
|
+
- lib/rails_best_practices/checks/overuse_route_customizations_check.rb
|
152
169
|
- lib/rails_best_practices/checks/replace_complex_creation_with_factory_method_check.rb
|
153
|
-
- lib/rails_best_practices/checks/dry_bundler_in_capistrano_check.rb
|
154
|
-
- lib/rails_best_practices/checks/isolate_seed_data_check.rb
|
155
|
-
- lib/rails_best_practices/checks/always_add_db_index_check.rb
|
156
170
|
- lib/rails_best_practices/checks/replace_instance_variable_with_local_variable_check.rb
|
157
|
-
- lib/rails_best_practices/checks/
|
158
|
-
- lib/rails_best_practices/checks/
|
171
|
+
- lib/rails_best_practices/checks/use_before_filter_check.rb
|
172
|
+
- lib/rails_best_practices/checks/use_model_association_check.rb
|
159
173
|
- lib/rails_best_practices/checks/use_observer_check.rb
|
160
|
-
- lib/rails_best_practices/checks/check.rb
|
161
|
-
- lib/rails_best_practices/checks/overuse_route_customizations_check.rb
|
162
174
|
- lib/rails_best_practices/checks/use_query_attribute_check.rb
|
163
|
-
- lib/rails_best_practices/checks/
|
164
|
-
- lib/rails_best_practices/checks/
|
165
|
-
- lib/rails_best_practices/core.rb
|
175
|
+
- lib/rails_best_practices/checks/use_say_with_time_in_migrations_check.rb
|
176
|
+
- lib/rails_best_practices/checks/use_scope_access_check.rb
|
166
177
|
- lib/rails_best_practices/checks.rb
|
178
|
+
- lib/rails_best_practices/command.rb
|
167
179
|
- lib/rails_best_practices/core/checking_visitor.rb
|
168
180
|
- lib/rails_best_practices/core/core_ext.rb
|
169
181
|
- lib/rails_best_practices/core/error.rb
|
170
|
-
- lib/rails_best_practices/core/visitable_sexp.rb
|
171
182
|
- lib/rails_best_practices/core/runner.rb
|
172
|
-
- lib/rails_best_practices/
|
183
|
+
- lib/rails_best_practices/core/visitable_sexp.rb
|
184
|
+
- lib/rails_best_practices/core.rb
|
185
|
+
- lib/rails_best_practices/version.rb
|
186
|
+
- lib/rails_best_practices.rb
|
173
187
|
- rails_best_practices.yml
|
174
188
|
- MIT_LICENSE
|
175
189
|
- README.textile
|