rails_best_practices 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
@@ -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
|