rails_best_practices 1.5.2 → 1.5.3
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/Gemfile.lock +1 -1
- data/README.md +1 -0
- data/assets/result.html.erb +8 -2
- data/lib/rails_best_practices.rb +1 -217
- data/lib/rails_best_practices/analyzer.rb +239 -0
- data/lib/rails_best_practices/command.rb +9 -2
- data/lib/rails_best_practices/core/error.rb +1 -1
- data/lib/rails_best_practices/core/runner.rb +1 -1
- data/lib/rails_best_practices/version.rb +1 -1
- data/rails_best_practices.gemspec +1 -1
- data/spec/rails_best_practices/analyzer_spec.rb +45 -0
- metadata +27 -25
- data/spec/rails_best_practices_spec.rb +0 -43
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -28,6 +28,7 @@ By default rails_best_practices will do parse codes in vendor, spec, test and fe
|
|
28
28
|
--with-textmate open file by textmate in html format
|
29
29
|
--with-mvim open file by mvim in html format
|
30
30
|
--with-git display git commit and git username in html format
|
31
|
+
--with-hg display hg commit and hg username in html format
|
31
32
|
--vendor include vendor files
|
32
33
|
--spec include spec files
|
33
34
|
--test include test files
|
data/assets/result.html.erb
CHANGED
@@ -73,7 +73,10 @@
|
|
73
73
|
<th>Filename</th>
|
74
74
|
<th>Line Number</th>
|
75
75
|
<th>Warning Message</th>
|
76
|
-
<% if @
|
76
|
+
<% if @hg %>
|
77
|
+
<th>Hg Commit</th>
|
78
|
+
<th>Hg Username</th>
|
79
|
+
<% elsif @git %>
|
77
80
|
<th>Git Commit</th>
|
78
81
|
<th>Git Username</th>
|
79
82
|
<% end %>
|
@@ -93,7 +96,10 @@
|
|
93
96
|
<td class='message'>
|
94
97
|
<a href='<%= error.url %>' target='_blank'><%= error.message %></a>
|
95
98
|
</td>
|
96
|
-
<% if @
|
99
|
+
<% if @hg %>
|
100
|
+
<td class='hg_commit'><%= error.hg_commit %></td>
|
101
|
+
<td class='hg_usename'><%= error.hg_username %></td>
|
102
|
+
<% elsif @git %>
|
97
103
|
<td class='git_commit'><%= error.git_commit %></td>
|
98
104
|
<td class='git_usename'><%= error.git_username %></td>
|
99
105
|
<% end %>
|
data/lib/rails_best_practices.rb
CHANGED
@@ -22,227 +22,11 @@
|
|
22
22
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
23
23
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
24
24
|
#++
|
25
|
-
require 'fileutils'
|
26
|
-
|
27
|
-
require 'progressbar'
|
28
|
-
require 'colored'
|
29
|
-
|
30
25
|
require 'rails_best_practices/lexicals'
|
31
26
|
require 'rails_best_practices/prepares'
|
32
27
|
require 'rails_best_practices/reviews'
|
33
28
|
require 'rails_best_practices/core'
|
29
|
+
require 'rails_best_practices/analyzer'
|
34
30
|
|
35
|
-
# RailsBestPractices helps you to analyze your rails code, according to best practices on http://rails-bestpractices.
|
36
|
-
# if it finds any violatioins to best practices, it will give you some readable suggestions.
|
37
|
-
#
|
38
|
-
# The analysis process is partitioned into two parts,
|
39
|
-
#
|
40
|
-
# 1. prepare process, it checks only model and mailer files, do some preparations, such as remember model names and associations.
|
41
|
-
# 2. review process, it checks all files, according to configuration, it really check if codes violate the best practices, if so, remember the violations.
|
42
|
-
#
|
43
|
-
# After analyzing, output the violations.
|
44
31
|
module RailsBestPractices
|
45
|
-
|
46
|
-
DEFAULT_CONFIG = File.join(File.dirname(__FILE__), "..", "rails_best_practices.yml")
|
47
|
-
|
48
|
-
class <<self
|
49
|
-
attr_writer :runner
|
50
|
-
|
51
|
-
# generate configuration yaml file.
|
52
|
-
#
|
53
|
-
# @param [String] path where to generate the configuration yaml file
|
54
|
-
def generate(path)
|
55
|
-
@path = path || '.'
|
56
|
-
FileUtils.cp DEFAULT_CONFIG, File.join(@path, 'config/rails_best_practices.yml')
|
57
|
-
end
|
58
|
-
|
59
|
-
# start checking rails codes.
|
60
|
-
#
|
61
|
-
# there are two steps to check rails codes,
|
62
|
-
#
|
63
|
-
# 1. prepare process, check all model and mailer files.
|
64
|
-
# 2. review process, check all files.
|
65
|
-
#
|
66
|
-
# if there are violations to rails best practices, output them.
|
67
|
-
#
|
68
|
-
# @param [String] path the directory of rails project
|
69
|
-
# @param [Hash] options
|
70
|
-
def start(path, options)
|
71
|
-
@path = path || '.'
|
72
|
-
@options = options
|
73
|
-
@options[:exclude] ||= []
|
74
|
-
|
75
|
-
Core::Runner.base_path = @path
|
76
|
-
@runner = Core::Runner.new
|
77
|
-
@runner.debug = true if @options['debug']
|
78
|
-
@runner.color = !options['without-color']
|
79
|
-
|
80
|
-
if @runner.checks.find { |check| check.is_a? Reviews::AlwaysAddDbIndexReview } &&
|
81
|
-
!parse_files.find { |file| file.index "db\/schema.rb" }
|
82
|
-
plain_output("AlwaysAddDbIndexReview is disabled as there is no db/schema.rb file in your rails project.", 'blue')
|
83
|
-
end
|
84
|
-
|
85
|
-
@bar = ProgressBar.new('Source Codes', parse_files.size * 3)
|
86
|
-
["lexical", "prepare", "review"].each { |process| send(:process, process) }
|
87
|
-
@runner.on_complete
|
88
|
-
@bar.finish
|
89
|
-
|
90
|
-
if @options['format'] == 'html'
|
91
|
-
load_git_info if @options["with-git"]
|
92
|
-
output_html_errors
|
93
|
-
else
|
94
|
-
output_terminal_errors
|
95
|
-
end
|
96
|
-
exit @runner.errors.size
|
97
|
-
end
|
98
|
-
|
99
|
-
# process lexical, prepare or reivew.
|
100
|
-
#
|
101
|
-
# get all files for the process, analyze each file,
|
102
|
-
# and increment progress bar unless debug.
|
103
|
-
#
|
104
|
-
# @param [String] process the process name, lexical, prepare or review.
|
105
|
-
def process(process)
|
106
|
-
parse_files.each do |file|
|
107
|
-
@runner.send("#{process}_file", file)
|
108
|
-
@bar.inc unless @options['debug']
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
# get all files for parsing.
|
113
|
-
#
|
114
|
-
# @return [Array] all files for parsing
|
115
|
-
def parse_files
|
116
|
-
@parse_files ||= begin
|
117
|
-
files = expand_dirs_to_files(@path)
|
118
|
-
files = file_sort(files)
|
119
|
-
|
120
|
-
# By default, tmp, vender, spec, test, features are ignored.
|
121
|
-
['vendor', 'spec', 'test', 'features', 'tmp'].each do |pattern|
|
122
|
-
files = file_ignore(files, "#{pattern}/") unless @options[pattern]
|
123
|
-
end
|
124
|
-
|
125
|
-
# Exclude files based on exclude regexes if the option is set.
|
126
|
-
@options[:exclude].each do |pattern|
|
127
|
-
files = file_ignore(files, pattern)
|
128
|
-
end
|
129
|
-
|
130
|
-
files.compact
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
# expand all files with extenstion rb, erb, haml and builder under the dirs
|
135
|
-
#
|
136
|
-
# @param [Array] dirs what directories to expand
|
137
|
-
# @return [Array] all files expanded
|
138
|
-
def expand_dirs_to_files *dirs
|
139
|
-
extensions = ['rb', 'erb', 'rake', 'rhtml', 'haml', 'builder']
|
140
|
-
|
141
|
-
dirs.flatten.map { |entry|
|
142
|
-
next unless File.exist? entry
|
143
|
-
if File.directory? entry
|
144
|
-
Dir[File.join(entry, '**', "*.{#{extensions.join(',')}}")]
|
145
|
-
else
|
146
|
-
entry
|
147
|
-
end
|
148
|
-
}.flatten
|
149
|
-
end
|
150
|
-
|
151
|
-
|
152
|
-
# sort files, models first, then mailers, and sort other files by characters.
|
153
|
-
#
|
154
|
-
# models and mailers first as for prepare process.
|
155
|
-
#
|
156
|
-
# @param [Array] files
|
157
|
-
# @return [Array] sorted files
|
158
|
-
def file_sort files
|
159
|
-
models = []
|
160
|
-
mailers = []
|
161
|
-
files.each do |a|
|
162
|
-
if a =~ Core::Check::MODEL_FILES
|
163
|
-
models << a
|
164
|
-
end
|
165
|
-
end
|
166
|
-
files.each do |a|
|
167
|
-
if a =~ Core::Check::MAILER_FILES
|
168
|
-
mailers << a
|
169
|
-
end
|
170
|
-
end
|
171
|
-
files.collect! do |a|
|
172
|
-
if a =~ Core::Check::MAILER_FILES || a =~ Core::Check::MODEL_FILES
|
173
|
-
#nil
|
174
|
-
else
|
175
|
-
a
|
176
|
-
end
|
177
|
-
end
|
178
|
-
files.compact!
|
179
|
-
models.sort
|
180
|
-
mailers.sort
|
181
|
-
files.sort
|
182
|
-
return models + mailers + files
|
183
|
-
end
|
184
|
-
|
185
|
-
# ignore specific files.
|
186
|
-
#
|
187
|
-
# @param [Array] files
|
188
|
-
# @param [Regexp] pattern files match the pattern will be ignored
|
189
|
-
# @return [Array] files that not match the pattern
|
190
|
-
def file_ignore files, pattern
|
191
|
-
files.reject { |file| file.index(pattern) }
|
192
|
-
end
|
193
|
-
|
194
|
-
# output errors on terminal.
|
195
|
-
def output_terminal_errors
|
196
|
-
@runner.errors.each { |error| plain_output(error.to_s, 'red') }
|
197
|
-
plain_output("\nPlease go to http://rails-bestpractices.com to see more useful Rails Best Practices.", 'green')
|
198
|
-
if @runner.errors.empty?
|
199
|
-
plain_output("\nNo warning found. Cool!", 'green')
|
200
|
-
else
|
201
|
-
plain_output("\nFound #{@runner.errors.size} warnings.", 'red')
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
205
|
-
# load git commit and git username info.
|
206
|
-
def load_git_info
|
207
|
-
git_progressbar = ProgressBar.new('Git Info', @runner.errors.size)
|
208
|
-
@runner.errors.each do |error|
|
209
|
-
git_info = `cd #{@runner.class.base_path}; git blame #{error.filename[@runner.class.base_path.size..-1]} | sed -n #{error.line_number.split(',').first}p`
|
210
|
-
unless git_info == ""
|
211
|
-
git_commit, git_username = git_info.split(/\d{4}-\d{2}-\d{2}/).first.split("(")
|
212
|
-
error.git_commit = git_commit.split(" ").first.strip
|
213
|
-
error.git_username = git_username.strip
|
214
|
-
end
|
215
|
-
git_progressbar.inc unless @options['debug']
|
216
|
-
end
|
217
|
-
git_progressbar.finish
|
218
|
-
end
|
219
|
-
|
220
|
-
# output errors with html format.
|
221
|
-
def output_html_errors
|
222
|
-
require 'erubis'
|
223
|
-
template = File.read(File.join(File.dirname(__FILE__), "..", "assets", "result.html.erb"))
|
224
|
-
|
225
|
-
File.open("rails_best_practices_output.html", "w+") do |file|
|
226
|
-
eruby = Erubis::Eruby.new(template)
|
227
|
-
file.puts eruby.evaluate(:errors => @runner.errors, :error_types => error_types, :textmate => @options["with-textmate"], :mvim => @options["with-mvim"], :git => @options["with-git"])
|
228
|
-
end
|
229
|
-
end
|
230
|
-
|
231
|
-
# plain output with color.
|
232
|
-
#
|
233
|
-
# @param [String] message to output
|
234
|
-
# @param [String] color
|
235
|
-
def plain_output(message, color)
|
236
|
-
if @options["without-color"]
|
237
|
-
puts message
|
238
|
-
else
|
239
|
-
puts message.send(color)
|
240
|
-
end
|
241
|
-
end
|
242
|
-
|
243
|
-
# unique error types.
|
244
|
-
def error_types
|
245
|
-
@runner.errors.map(&:type).uniq
|
246
|
-
end
|
247
|
-
end
|
248
32
|
end
|
@@ -0,0 +1,239 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
require 'progressbar'
|
5
|
+
require 'colored'
|
6
|
+
|
7
|
+
module RailsBestPractices
|
8
|
+
# RailsBestPractices Analyzer helps you to analyze your rails code, according to best practices on http://rails-bestpractices.
|
9
|
+
# if it finds any violatioins to best practices, it will give you some readable suggestions.
|
10
|
+
#
|
11
|
+
# The analysis process is partitioned into two parts,
|
12
|
+
#
|
13
|
+
# 1. prepare process, it checks only model and mailer files, do some preparations, such as remember model names and associations.
|
14
|
+
# 2. review process, it checks all files, according to configuration, it really check if codes violate the best practices, if so, remember the violations.
|
15
|
+
#
|
16
|
+
# After analyzing, output the violations.
|
17
|
+
class Analyzer
|
18
|
+
attr_accessor :runner
|
19
|
+
|
20
|
+
DEFAULT_CONFIG = File.join(File.dirname(__FILE__), "..", "..", "rails_best_practices.yml")
|
21
|
+
|
22
|
+
# initialize
|
23
|
+
#
|
24
|
+
# @param [String] path where to generate the configuration yaml file
|
25
|
+
# @param [Hash] options
|
26
|
+
def initialize(path, options={})
|
27
|
+
@path = path || "."
|
28
|
+
@options = options
|
29
|
+
end
|
30
|
+
|
31
|
+
# generate configuration yaml file.
|
32
|
+
def generate
|
33
|
+
FileUtils.cp DEFAULT_CONFIG, File.join(@path, 'config/rails_best_practices.yml')
|
34
|
+
end
|
35
|
+
|
36
|
+
# Analyze rails codes.
|
37
|
+
#
|
38
|
+
# there are two steps to check rails codes,
|
39
|
+
#
|
40
|
+
# 1. prepare process, check all model and mailer files.
|
41
|
+
# 2. review process, check all files.
|
42
|
+
#
|
43
|
+
# if there are violations to rails best practices, output them.
|
44
|
+
#
|
45
|
+
# @param [String] path the directory of rails project
|
46
|
+
# @param [Hash] options
|
47
|
+
def analyze
|
48
|
+
@options[:exclude] ||= []
|
49
|
+
|
50
|
+
Core::Runner.base_path = @path
|
51
|
+
@runner = Core::Runner.new
|
52
|
+
@runner.debug = true if @options['debug']
|
53
|
+
@runner.color = !@options['without-color']
|
54
|
+
|
55
|
+
@bar = ProgressBar.new('Source Codes', parse_files.size * 3)
|
56
|
+
["lexical", "prepare", "review"].each { |process| send(:process, process) }
|
57
|
+
@runner.on_complete
|
58
|
+
@bar.finish
|
59
|
+
end
|
60
|
+
|
61
|
+
# Output the analyze result.
|
62
|
+
def output
|
63
|
+
if @options['format'] == 'html'
|
64
|
+
if @options["with-hg"]
|
65
|
+
load_hg_info
|
66
|
+
elsif @options["with-git"]
|
67
|
+
load_git_info
|
68
|
+
end
|
69
|
+
output_html_errors
|
70
|
+
else
|
71
|
+
output_terminal_errors
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# process lexical, prepare or reivew.
|
76
|
+
#
|
77
|
+
# get all files for the process, analyze each file,
|
78
|
+
# and increment progress bar unless debug.
|
79
|
+
#
|
80
|
+
# @param [String] process the process name, lexical, prepare or review.
|
81
|
+
def process(process)
|
82
|
+
parse_files.each do |file|
|
83
|
+
@runner.send("#{process}_file", file)
|
84
|
+
@bar.inc unless @options['debug']
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# get all files for parsing.
|
89
|
+
#
|
90
|
+
# @return [Array] all files for parsing
|
91
|
+
def parse_files
|
92
|
+
@parse_files ||= begin
|
93
|
+
files = expand_dirs_to_files(@path)
|
94
|
+
files = file_sort(files)
|
95
|
+
|
96
|
+
# By default, tmp, vender, spec, test, features are ignored.
|
97
|
+
['vendor', 'spec', 'test', 'features', 'tmp'].each do |pattern|
|
98
|
+
files = file_ignore(files, "#{pattern}/") unless @options[pattern]
|
99
|
+
end
|
100
|
+
|
101
|
+
# Exclude files based on exclude regexes if the option is set.
|
102
|
+
@options[:exclude].each do |pattern|
|
103
|
+
files = file_ignore(files, pattern)
|
104
|
+
end
|
105
|
+
|
106
|
+
files.compact
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# expand all files with extenstion rb, erb, haml and builder under the dirs
|
111
|
+
#
|
112
|
+
# @param [Array] dirs what directories to expand
|
113
|
+
# @return [Array] all files expanded
|
114
|
+
def expand_dirs_to_files *dirs
|
115
|
+
extensions = ['rb', 'erb', 'rake', 'rhtml', 'haml', 'builder']
|
116
|
+
|
117
|
+
dirs.flatten.map { |entry|
|
118
|
+
next unless File.exist? entry
|
119
|
+
if File.directory? entry
|
120
|
+
Dir[File.join(entry, '**', "*.{#{extensions.join(',')}}")]
|
121
|
+
else
|
122
|
+
entry
|
123
|
+
end
|
124
|
+
}.flatten
|
125
|
+
end
|
126
|
+
|
127
|
+
|
128
|
+
# sort files, models first, then mailers, and sort other files by characters.
|
129
|
+
#
|
130
|
+
# models and mailers first as for prepare process.
|
131
|
+
#
|
132
|
+
# @param [Array] files
|
133
|
+
# @return [Array] sorted files
|
134
|
+
def file_sort files
|
135
|
+
models = []
|
136
|
+
mailers = []
|
137
|
+
files.each do |a|
|
138
|
+
if a =~ Core::Check::MODEL_FILES
|
139
|
+
models << a
|
140
|
+
end
|
141
|
+
end
|
142
|
+
files.each do |a|
|
143
|
+
if a =~ Core::Check::MAILER_FILES
|
144
|
+
mailers << a
|
145
|
+
end
|
146
|
+
end
|
147
|
+
files.collect! do |a|
|
148
|
+
if a =~ Core::Check::MAILER_FILES || a =~ Core::Check::MODEL_FILES
|
149
|
+
#nil
|
150
|
+
else
|
151
|
+
a
|
152
|
+
end
|
153
|
+
end
|
154
|
+
files.compact!
|
155
|
+
models.sort
|
156
|
+
mailers.sort
|
157
|
+
files.sort
|
158
|
+
return models + mailers + files
|
159
|
+
end
|
160
|
+
|
161
|
+
# ignore specific files.
|
162
|
+
#
|
163
|
+
# @param [Array] files
|
164
|
+
# @param [Regexp] pattern files match the pattern will be ignored
|
165
|
+
# @return [Array] files that not match the pattern
|
166
|
+
def file_ignore files, pattern
|
167
|
+
files.reject { |file| file.index(pattern) }
|
168
|
+
end
|
169
|
+
|
170
|
+
# output errors on terminal.
|
171
|
+
def output_terminal_errors
|
172
|
+
@runner.errors.each { |error| plain_output(error.to_s, 'red') }
|
173
|
+
plain_output("\nPlease go to http://rails-bestpractices.com to see more useful Rails Best Practices.", 'green')
|
174
|
+
if @runner.errors.empty?
|
175
|
+
plain_output("\nNo warning found. Cool!", 'green')
|
176
|
+
else
|
177
|
+
plain_output("\nFound #{@runner.errors.size} warnings.", 'red')
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
# load hg commit and hg username info.
|
182
|
+
def load_hg_info
|
183
|
+
hg_progressbar = ProgressBar.new('Hg Info', @runner.errors.size)
|
184
|
+
@runner.errors.each do |error|
|
185
|
+
hg_info = `cd #{@runner.class.base_path}; hg blame -lvcu #{error.filename[@runner.class.base_path.size..-1].gsub(/^\//, "")} | sed -n /:#{error.line_number.split(',').first}:/p`
|
186
|
+
unless hg_info == ""
|
187
|
+
hg_commit_username = hg_info.split(':')[0].strip
|
188
|
+
error.hg_username = hg_commit_username.split(/\ /)[0..-2].join(' ')
|
189
|
+
error.hg_commit = hg_commit_username.split(/\ /)[-1]
|
190
|
+
end
|
191
|
+
hg_progressbar.inc unless @options['debug']
|
192
|
+
end
|
193
|
+
hg_progressbar.finish
|
194
|
+
end
|
195
|
+
|
196
|
+
# load git commit and git username info.
|
197
|
+
def load_git_info
|
198
|
+
git_progressbar = ProgressBar.new('Git Info', @runner.errors.size)
|
199
|
+
@runner.errors.each do |error|
|
200
|
+
git_info = `cd #{@runner.class.base_path}; git blame #{error.filename[@runner.class.base_path.size..-1]} | sed -n #{error.line_number.split(',').first}p`
|
201
|
+
unless git_info == ""
|
202
|
+
git_commit, git_username = git_info.split(/\d{4}-\d{2}-\d{2}/).first.split("(")
|
203
|
+
error.git_commit = git_commit.split(" ").first.strip
|
204
|
+
error.git_username = git_username.strip
|
205
|
+
end
|
206
|
+
git_progressbar.inc unless @options['debug']
|
207
|
+
end
|
208
|
+
git_progressbar.finish
|
209
|
+
end
|
210
|
+
|
211
|
+
# output errors with html format.
|
212
|
+
def output_html_errors
|
213
|
+
require 'erubis'
|
214
|
+
template = File.read(File.join(File.dirname(__FILE__), "..", "..", "assets", "result.html.erb"))
|
215
|
+
|
216
|
+
File.open("rails_best_practices_output.html", "w+") do |file|
|
217
|
+
eruby = Erubis::Eruby.new(template)
|
218
|
+
file.puts eruby.evaluate(:errors => @runner.errors, :error_types => error_types, :textmate => @options["with-textmate"], :mvim => @options["with-mvim"], :git => @options["with-git"], :hg => @options["with-hg"])
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
# plain output with color.
|
223
|
+
#
|
224
|
+
# @param [String] message to output
|
225
|
+
# @param [String] color
|
226
|
+
def plain_output(message, color)
|
227
|
+
if @options["without-color"]
|
228
|
+
puts message
|
229
|
+
else
|
230
|
+
puts message.send(color)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
# unique error types.
|
235
|
+
def error_types
|
236
|
+
@runner.errors.map(&:type).uniq
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
@@ -40,6 +40,10 @@ OptionParser.new do |opts|
|
|
40
40
|
options["with-mvim"] = true
|
41
41
|
end
|
42
42
|
|
43
|
+
opts.on("--with-hg", "display hg commit and username, only support html format") do
|
44
|
+
options["with-hg"] = true
|
45
|
+
end
|
46
|
+
|
43
47
|
opts.on("--with-git", "display git commit and username, only support html format") do
|
44
48
|
options["with-git"] = true
|
45
49
|
end
|
@@ -77,7 +81,10 @@ OptionParser.new do |opts|
|
|
77
81
|
end
|
78
82
|
|
79
83
|
if options[:generate]
|
80
|
-
RailsBestPractices.
|
84
|
+
RailsBestPractices::Analyzer.new(ARGV.first).generate
|
81
85
|
else
|
82
|
-
RailsBestPractices.
|
86
|
+
analyzer = RailsBestPractices::Analyzer.new(ARGV.first, options)
|
87
|
+
analyzer.analyze
|
88
|
+
analyzer.output
|
89
|
+
exit analyzer.runner.errors.size
|
83
90
|
end
|
@@ -6,7 +6,7 @@ module RailsBestPractices
|
|
6
6
|
# it indicates the filenname, line number and error message for the violation.
|
7
7
|
class Error
|
8
8
|
attr_reader :filename, :line_number, :message, :type, :url
|
9
|
-
attr_accessor :git_commit, :git_username
|
9
|
+
attr_accessor :git_commit, :git_username, :hg_commit, :hg_username
|
10
10
|
|
11
11
|
def initialize(filename, line_number, message, type, url = nil)
|
12
12
|
@filename = filename
|
@@ -35,7 +35,7 @@ module RailsBestPractices
|
|
35
35
|
# @param [Hash] options pass the prepares and reviews.
|
36
36
|
def initialize(options={})
|
37
37
|
custom_config = File.join(Runner.base_path, 'config/rails_best_practices.yml')
|
38
|
-
@config = File.exists?(custom_config) ? custom_config : RailsBestPractices::DEFAULT_CONFIG
|
38
|
+
@config = File.exists?(custom_config) ? custom_config : RailsBestPractices::Analyzer::DEFAULT_CONFIG
|
39
39
|
|
40
40
|
lexicals = Array(options[:lexicals])
|
41
41
|
prepares = Array(options[:prepares])
|
@@ -28,7 +28,7 @@ Gem::Specification.new do |s|
|
|
28
28
|
s.files = `git ls-files`.split("\n")
|
29
29
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
30
30
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
31
|
-
s.require_paths = ["lib"]
|
31
|
+
s.require_paths = ["lib", "assets"]
|
32
32
|
|
33
33
|
s.post_install_message = <<-POST_INSTALL_MESSAGE
|
34
34
|
#{"*" * 80}
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RailsBestPractices::Analyzer do
|
4
|
+
subject { RailsBestPractices::Analyzer.new(".") }
|
5
|
+
|
6
|
+
describe "expand_dirs_to_files" do
|
7
|
+
it "should expand all files in spec directory" do
|
8
|
+
dir = File.dirname(__FILE__)
|
9
|
+
subject.expand_dirs_to_files(dir).should be_include(dir + '/analyzer_spec.rb')
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "file_sort" do
|
14
|
+
it "should get models first, then mailers" do
|
15
|
+
files = ["app/controllers/users_controller.rb", "app/mailers/user_mailer.rb", "app/models/user.rb", "app/views/users/index.html.haml", "lib/user.rb"]
|
16
|
+
subject.file_sort(files).should == ["app/models/user.rb", "app/mailers/user_mailer.rb", "app/controllers/users_controller.rb", "app/views/users/index.html.haml", "lib/user.rb"]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "file_ignore" do
|
21
|
+
it "should ignore lib" do
|
22
|
+
files = ["app/controllers/users_controller.rb", "app/mailers/user_mailer.rb", "app/models/user.rb", "app/views/users/index.html.haml", "lib/user.rb"]
|
23
|
+
subject.file_ignore(files, 'lib/').should == ["app/controllers/users_controller.rb", "app/mailers/user_mailer.rb", "app/models/user.rb", "app/views/users/index.html.haml"]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "output_terminal_errors" do
|
28
|
+
it "should output errors in terminal" do
|
29
|
+
check1 = RailsBestPractices::Reviews::LawOfDemeterReview.new
|
30
|
+
check2 = RailsBestPractices::Reviews::UseQueryAttributeReview.new
|
31
|
+
runner = RailsBestPractices::Core::Runner.new(:reviews => [check1, check2])
|
32
|
+
check1.add_error "law of demeter", "app/models/user.rb", 10
|
33
|
+
check2.add_error "use query attribute", "app/models/post.rb", 100
|
34
|
+
subject.runner = runner
|
35
|
+
subject.instance_variable_set("@options", {"without-color" => false})
|
36
|
+
|
37
|
+
$origin_stdout = $stdout
|
38
|
+
$stdout = StringIO.new
|
39
|
+
subject.output_terminal_errors
|
40
|
+
result = $stdout.string
|
41
|
+
$stdout = $origin_stdout
|
42
|
+
result.should == ["app/models/user.rb:10 - law of demeter".red, "app/models/post.rb:100 - use query attribute".red, "\nPlease go to http://rails-bestpractices.com to see more useful Rails Best Practices.".green, "\nFound 2 warnings.".red].join("\n") + "\n"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails_best_practices
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.5.
|
4
|
+
version: 1.5.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-11-
|
12
|
+
date: 2011-11-30 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: sexp_processor
|
16
|
-
requirement: &
|
16
|
+
requirement: &70221608963020 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70221608963020
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: progressbar
|
27
|
-
requirement: &
|
27
|
+
requirement: &70221608962100 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70221608962100
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: colored
|
38
|
-
requirement: &
|
38
|
+
requirement: &70221608961120 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70221608961120
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: erubis
|
49
|
-
requirement: &
|
49
|
+
requirement: &70221608960060 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70221608960060
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: i18n
|
60
|
-
requirement: &
|
60
|
+
requirement: &70221608959000 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :runtime
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70221608959000
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: activesupport
|
71
|
-
requirement: &
|
71
|
+
requirement: &70221608958140 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70221608958140
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: rake
|
82
|
-
requirement: &
|
82
|
+
requirement: &70221608957540 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *70221608957540
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: rspec
|
93
|
-
requirement: &
|
93
|
+
requirement: &70221608956760 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ! '>='
|
@@ -98,10 +98,10 @@ dependencies:
|
|
98
98
|
version: '0'
|
99
99
|
type: :development
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *70221608956760
|
102
102
|
- !ruby/object:Gem::Dependency
|
103
103
|
name: haml
|
104
|
-
requirement: &
|
104
|
+
requirement: &70221608955200 !ruby/object:Gem::Requirement
|
105
105
|
none: false
|
106
106
|
requirements:
|
107
107
|
- - ! '>='
|
@@ -109,10 +109,10 @@ dependencies:
|
|
109
109
|
version: '0'
|
110
110
|
type: :development
|
111
111
|
prerelease: false
|
112
|
-
version_requirements: *
|
112
|
+
version_requirements: *70221608955200
|
113
113
|
- !ruby/object:Gem::Dependency
|
114
114
|
name: bundler
|
115
|
-
requirement: &
|
115
|
+
requirement: &70221608954440 !ruby/object:Gem::Requirement
|
116
116
|
none: false
|
117
117
|
requirements:
|
118
118
|
- - ! '>='
|
@@ -120,7 +120,7 @@ dependencies:
|
|
120
120
|
version: '0'
|
121
121
|
type: :development
|
122
122
|
prerelease: false
|
123
|
-
version_requirements: *
|
123
|
+
version_requirements: *70221608954440
|
124
124
|
description: a code metric tool for rails codes, written in Ruby.
|
125
125
|
email:
|
126
126
|
- flyerhzm@gmail.com
|
@@ -148,6 +148,7 @@ files:
|
|
148
148
|
- bin/rails_best_practices
|
149
149
|
- install_supported_rubies.sh
|
150
150
|
- lib/rails_best_practices.rb
|
151
|
+
- lib/rails_best_practices/analyzer.rb
|
151
152
|
- lib/rails_best_practices/command.rb
|
152
153
|
- lib/rails_best_practices/core.rb
|
153
154
|
- lib/rails_best_practices/core/check.rb
|
@@ -211,6 +212,7 @@ files:
|
|
211
212
|
- rails_best_practices.yml
|
212
213
|
- rake_rubies.sh
|
213
214
|
- spec/fixtures/lib/rails_best_practices/plugins/reviews/not_use_rails_root_review.rb
|
215
|
+
- spec/rails_best_practices/analyzer_spec.rb
|
214
216
|
- spec/rails_best_practices/core/check_spec.rb
|
215
217
|
- spec/rails_best_practices/core/checking_visitor_spec.rb
|
216
218
|
- spec/rails_best_practices/core/controllers_spec.rb
|
@@ -263,7 +265,6 @@ files:
|
|
263
265
|
- spec/rails_best_practices/reviews/use_query_attribute_review_spec.rb
|
264
266
|
- spec/rails_best_practices/reviews/use_say_with_time_in_migrations_review_spec.rb
|
265
267
|
- spec/rails_best_practices/reviews/use_scope_access_review_spec.rb
|
266
|
-
- spec/rails_best_practices_spec.rb
|
267
268
|
- spec/spec_helper.rb
|
268
269
|
homepage: http://rails-bestpractices.com
|
269
270
|
licenses: []
|
@@ -274,6 +275,7 @@ post_install_message: ! "*******************************************************
|
|
274
275
|
rdoc_options: []
|
275
276
|
require_paths:
|
276
277
|
- lib
|
278
|
+
- assets
|
277
279
|
required_ruby_version: !ruby/object:Gem::Requirement
|
278
280
|
none: false
|
279
281
|
requirements:
|
@@ -282,7 +284,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
282
284
|
version: '0'
|
283
285
|
segments:
|
284
286
|
- 0
|
285
|
-
hash:
|
287
|
+
hash: 1044082634186330916
|
286
288
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
287
289
|
none: false
|
288
290
|
requirements:
|
@@ -297,6 +299,7 @@ specification_version: 3
|
|
297
299
|
summary: a code metric tool for rails codes.
|
298
300
|
test_files:
|
299
301
|
- spec/fixtures/lib/rails_best_practices/plugins/reviews/not_use_rails_root_review.rb
|
302
|
+
- spec/rails_best_practices/analyzer_spec.rb
|
300
303
|
- spec/rails_best_practices/core/check_spec.rb
|
301
304
|
- spec/rails_best_practices/core/checking_visitor_spec.rb
|
302
305
|
- spec/rails_best_practices/core/controllers_spec.rb
|
@@ -349,5 +352,4 @@ test_files:
|
|
349
352
|
- spec/rails_best_practices/reviews/use_query_attribute_review_spec.rb
|
350
353
|
- spec/rails_best_practices/reviews/use_say_with_time_in_migrations_review_spec.rb
|
351
354
|
- spec/rails_best_practices/reviews/use_scope_access_review_spec.rb
|
352
|
-
- spec/rails_best_practices_spec.rb
|
353
355
|
- spec/spec_helper.rb
|
@@ -1,43 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe RailsBestPractices do
|
4
|
-
|
5
|
-
describe "expand_dirs_to_files" do
|
6
|
-
require 'find'
|
7
|
-
it "should expand all files in spec directory" do
|
8
|
-
dir = File.dirname(__FILE__)
|
9
|
-
RailsBestPractices.expand_dirs_to_files(dir).should be_include(dir + '/rails_best_practices_spec.rb')
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
describe "file_sort" do
|
14
|
-
it "should get models first, then mailers" do
|
15
|
-
files = ["app/controllers/users_controller.rb", "app/mailers/user_mailer.rb", "app/models/user.rb", "app/views/users/index.html.haml", "lib/user.rb"]
|
16
|
-
RailsBestPractices.file_sort(files).should == ["app/models/user.rb", "app/mailers/user_mailer.rb", "app/controllers/users_controller.rb", "app/views/users/index.html.haml", "lib/user.rb"]
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
describe "file_ignore" do
|
21
|
-
it "should ignore lib" do
|
22
|
-
files = ["app/controllers/users_controller.rb", "app/mailers/user_mailer.rb", "app/models/user.rb", "app/views/users/index.html.haml", "lib/user.rb"]
|
23
|
-
RailsBestPractices.file_ignore(files, 'lib/').should == ["app/controllers/users_controller.rb", "app/mailers/user_mailer.rb", "app/models/user.rb", "app/views/users/index.html.haml"]
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
describe "output_terminal_errors" do
|
28
|
-
check1 = RailsBestPractices::Reviews::LawOfDemeterReview.new
|
29
|
-
check2 = RailsBestPractices::Reviews::UseQueryAttributeReview.new
|
30
|
-
runner = RailsBestPractices::Core::Runner.new(:reviews => [check1, check2])
|
31
|
-
check1.add_error "law of demeter", "app/models/user.rb", 10
|
32
|
-
check2.add_error "use query attribute", "app/models/post.rb", 100
|
33
|
-
RailsBestPractices.runner = runner
|
34
|
-
RailsBestPractices.instance_variable_set("@options", {"without-color" => false})
|
35
|
-
|
36
|
-
$origin_stdout = $stdout
|
37
|
-
$stdout = StringIO.new
|
38
|
-
RailsBestPractices.output_terminal_errors
|
39
|
-
result = $stdout.string
|
40
|
-
$stdout = $origin_stdout
|
41
|
-
result.should == ["app/models/user.rb:10 - law of demeter".red, "app/models/post.rb:100 - use query attribute".red, "\nPlease go to http://rails-bestpractices.com to see more useful Rails Best Practices.".green, "\nFound 2 warnings.".red].join("\n") + "\n"
|
42
|
-
end
|
43
|
-
end
|