rails_best_practices 1.15.7 → 1.16.0
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.
- checksums.yaml +4 -4
- data/.rspec +1 -1
- data/.rubocop.yml +1 -0
- data/.rubocop_todo.yml +382 -0
- data/.travis.yml +1 -0
- data/CHANGELOG.md +88 -0
- data/README.md +31 -33
- data/Rakefile +4 -1
- data/lib/rails_best_practices.rb +1 -0
- data/lib/rails_best_practices/analyzer.rb +2 -3
- data/lib/rails_best_practices/colorize.rb +11 -0
- data/lib/rails_best_practices/core/modules.rb +8 -8
- data/lib/rails_best_practices/prepares/controller_prepare.rb +4 -4
- data/lib/rails_best_practices/reviews/check_destroy_return_value_review.rb +60 -0
- data/lib/rails_best_practices/reviews/check_save_return_value_review.rb +3 -3
- data/lib/rails_best_practices/reviews/remove_unused_methods_in_helpers_review.rb +3 -3
- data/lib/rails_best_practices/reviews/use_multipart_alternative_as_content_type_of_email_review.rb +2 -0
- data/lib/rails_best_practices/version.rb +1 -1
- data/rails_best_practices.gemspec +1 -1
- data/rails_best_practices.yml +1 -0
- data/spec/rails_best_practices/analyzer_spec.rb +5 -1
- data/spec/rails_best_practices/core/modules_spec.rb +5 -5
- data/spec/rails_best_practices/prepares/controller_prepare_spec.rb +2 -2
- data/spec/rails_best_practices/reviews/check_destroy_return_value_spec.rb +151 -0
- data/spec/rails_best_practices/reviews/remove_unused_methods_in_helpers_review_spec.rb +30 -0
- data/spec/rails_best_practices/reviews/use_multipart_alternative_as_content_type_of_email_review_spec.rb +12 -18
- metadata +24 -17
data/README.md
CHANGED
@@ -7,22 +7,22 @@
|
|
7
7
|
[](http://coderwall.com/flyerhzm)
|
8
8
|
[](https://pledgie.com/campaigns/12057)
|
9
9
|
|
10
|
-
rails_best_practices is a code metric tool to check the quality of
|
10
|
+
rails_best_practices is a code metric tool to check the quality of Rails code.
|
11
11
|
|
12
|
-
|
12
|
+
It supports the following ORM/ODMs:
|
13
13
|
|
14
14
|
* activerecord
|
15
15
|
* mongoid
|
16
16
|
* mongomapper
|
17
17
|
|
18
|
-
following template engines:
|
18
|
+
And the following template engines:
|
19
19
|
|
20
20
|
* erb
|
21
21
|
* haml
|
22
22
|
* slim
|
23
23
|
* rabl
|
24
24
|
|
25
|
-
rails_best_practices
|
25
|
+
rails_best_practices supports Ruby 1.9.3 or newer.
|
26
26
|
|
27
27
|
## External Introduction
|
28
28
|
|
@@ -32,29 +32,29 @@ rails_best_practices works well only in ruby 1.9.3, 2.0.0, and 2.1.0 so far. It
|
|
32
32
|
|
33
33
|
## Usage
|
34
34
|
|
35
|
-
At the root directory of
|
35
|
+
At the root directory of a Rails app, run:
|
36
36
|
|
37
37
|
rails_best_practices .
|
38
38
|
|
39
|
-
|
39
|
+
Or for HTML output:
|
40
40
|
|
41
41
|
rails_best_practices -f html .
|
42
42
|
|
43
|
-
By default rails_best_practices will
|
43
|
+
By default rails_best_practices will parse code in the `vendor`, `spec`, `test` and `features` directories.
|
44
44
|
|
45
|
-
### Excluding
|
45
|
+
### Excluding directories
|
46
46
|
|
47
|
-
To exclude
|
47
|
+
To exclude a directory simply call it with `-e` or `--exclude`:
|
48
48
|
|
49
49
|
rails_best_practices -e "db/migrate" .
|
50
50
|
|
51
|
-
To exclude multiple
|
51
|
+
To exclude multiple directories, separate them with comma:
|
52
52
|
|
53
53
|
rails_best_practices -e "db/migrate,vendor" .
|
54
54
|
|
55
|
-
### Other command
|
55
|
+
### Other command-line options
|
56
56
|
|
57
|
-
To see full list of
|
57
|
+
To see the full list of command-line options, run:
|
58
58
|
|
59
59
|
$ rails_best_practices -h
|
60
60
|
|
@@ -89,7 +89,7 @@ Homepage: <http://rails-bestpractices.com>
|
|
89
89
|
|
90
90
|
Online Service: <http://railsbp.com>
|
91
91
|
|
92
|
-
|
92
|
+
GitHub: <http://github.com/railsbp/rails_best_practices>
|
93
93
|
|
94
94
|
RDoc: <http://rdoc.rails-bestpractices.com>
|
95
95
|
|
@@ -103,11 +103,9 @@ Issue Tracker: <http://github.com/railsbp/rails_best_practices/issues>
|
|
103
103
|
|
104
104
|
## Install
|
105
105
|
|
106
|
-
rails_best_practices gem is rewritten based on ripper instead of ruby_parser to support ruby 1.9 new syntax.
|
107
|
-
|
108
106
|
gem install rails_best_practices
|
109
107
|
|
110
|
-
or add
|
108
|
+
or add it to the Gemfile
|
111
109
|
|
112
110
|
gem "rails_best_practices"
|
113
111
|
|
@@ -115,27 +113,27 @@ or add in Gemfile
|
|
115
113
|
|
116
114
|
Install <https://github.com/asuth/subl-handler>
|
117
115
|
|
118
|
-
##
|
116
|
+
## Issues
|
119
117
|
|
120
|
-
If you install the rails_best_practices with bundler-installed
|
118
|
+
If you install the rails_best_practices with bundler-installed GitHub-sourced gem, please use the following command instead.
|
121
119
|
|
122
120
|
bundle exec rails_best_practices .
|
123
121
|
|
124
|
-
If you
|
122
|
+
If you encounter a NoMethodError exception, or a syntax error, you can use debug mode to discover which file is to blame:
|
125
123
|
|
126
124
|
rails_best_practices -d .
|
127
125
|
|
128
|
-
|
126
|
+
That will provide the error's stack trace and the source code of the file which is causing the error.
|
129
127
|
|
130
|
-
##
|
128
|
+
## Custom Configuration
|
131
129
|
|
132
|
-
First run
|
130
|
+
First run:
|
133
131
|
|
134
132
|
rails_best_practices -g
|
135
133
|
|
136
134
|
to generate `rails_best_practices.yml` file.
|
137
135
|
|
138
|
-
Now you can customize this configuration file
|
136
|
+
Now you can customize this configuration file. The default configuration is as follows:
|
139
137
|
|
140
138
|
AddModelVirtualAttributeCheck: { }
|
141
139
|
AlwaysAddDbIndexCheck: { }
|
@@ -179,7 +177,7 @@ Now you can customize this configuration file, the default configuration is as f
|
|
179
177
|
UseScopeAccessCheck: { }
|
180
178
|
UseTurboSprocketsRails3Check: { }
|
181
179
|
|
182
|
-
You can remove or comment
|
180
|
+
You can remove or comment a review to disable it, and you can change the options.
|
183
181
|
|
184
182
|
You can apply the `ignored_files` option on any rule by giving a regexp or array of regexps describing the path of the files you don't want to be checked:
|
185
183
|
|
@@ -208,7 +206,7 @@ RESTful Conventions
|
|
208
206
|
Model
|
209
207
|
|
210
208
|
1. Keep finders on their own model (rails2 only)
|
211
|
-
2.
|
209
|
+
2. The law of demeter
|
212
210
|
3. Use observer
|
213
211
|
4. Use query attribute
|
214
212
|
5. Remove unused methods in models
|
@@ -221,12 +219,12 @@ Mailer
|
|
221
219
|
Migration
|
222
220
|
|
223
221
|
1. Isolating seed data
|
224
|
-
2. Always add
|
222
|
+
2. Always add database index
|
225
223
|
3. Use say with time in migrations
|
226
224
|
|
227
225
|
Controller
|
228
226
|
|
229
|
-
1. Use before_filter (disabled by default)
|
227
|
+
1. Use `before_filter` (disabled by default)
|
230
228
|
2. Simplify render in controllers
|
231
229
|
3. Remove unused methods in controllers
|
232
230
|
|
@@ -246,21 +244,21 @@ View
|
|
246
244
|
|
247
245
|
Deployment
|
248
246
|
|
249
|
-
1. Dry bundler in
|
250
|
-
2. Speed up assets
|
247
|
+
1. Dry bundler in Capistrano
|
248
|
+
2. Speed up assets precompilation with turbo-sprockets-rails3
|
251
249
|
|
252
250
|
Other
|
253
251
|
|
254
252
|
1. Remove trailing whitespace
|
255
253
|
2. Remove tab (disabled by default)
|
256
254
|
3. Hash syntax (disabled by default)
|
257
|
-
4. Use parentheses in method
|
255
|
+
4. Use parentheses in method definition (disabled by default)
|
258
256
|
5. Long line (disabled by default)
|
259
257
|
6. Not rescue exception
|
260
258
|
|
261
|
-
## Write Your Own
|
259
|
+
## Write Your Own Checklist
|
262
260
|
|
263
|
-
If you want to write your own
|
261
|
+
If you want to write your own checklist (some checklist only for your Rails projects), please read this first, [How to write your own check list?][1]
|
264
262
|
|
265
263
|
## Contribute
|
266
264
|
|
@@ -268,7 +266,7 @@ If you want to add your rails best practices into the gem, please post your best
|
|
268
266
|
|
269
267
|
## Contact Us
|
270
268
|
|
271
|
-
We provide
|
269
|
+
We provide Rails consulting services, you can contact us by Twitter or email.
|
272
270
|
|
273
271
|
Follow us on twitter: <http://twitter.com/railsbp>
|
274
272
|
|
data/Rakefile
CHANGED
@@ -6,6 +6,7 @@ Bundler.setup
|
|
6
6
|
require "rake"
|
7
7
|
require "rspec"
|
8
8
|
require "rspec/core/rake_task"
|
9
|
+
require 'rubocop/rake_task'
|
9
10
|
|
10
11
|
$LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
|
11
12
|
require "rails_best_practices/version"
|
@@ -14,5 +15,7 @@ RSpec::Core::RakeTask.new(:spec) do |spec|
|
|
14
15
|
spec.pattern = "spec/**/*_spec.rb"
|
15
16
|
end
|
16
17
|
|
17
|
-
|
18
|
+
RuboCop::RakeTask.new
|
19
|
+
|
20
|
+
task :default => [:spec, :rubocop]
|
18
21
|
task :test => :spec
|
data/lib/rails_best_practices.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
require 'colored'
|
3
2
|
require 'fileutils'
|
4
3
|
require 'json'
|
5
4
|
require 'ruby-progressbar'
|
@@ -308,13 +307,13 @@ module RailsBestPractices
|
|
308
307
|
if @options["without-color"]
|
309
308
|
puts message
|
310
309
|
else
|
311
|
-
puts
|
310
|
+
puts Colorize.send(color, message)
|
312
311
|
end
|
313
312
|
end
|
314
313
|
|
315
314
|
# analyze source codes.
|
316
315
|
def analyze_source_codes
|
317
|
-
@bar = ProgressBar.create(:title => 'Source
|
316
|
+
@bar = ProgressBar.create(:title => 'Source Code', :total => parse_files.size * 3) if display_bar?
|
318
317
|
["lexical", "prepare", "review"].each { |process| send(:process, process) }
|
319
318
|
@bar.finish if display_bar?
|
320
319
|
end
|
@@ -3,28 +3,28 @@ module RailsBestPractices
|
|
3
3
|
module Core
|
4
4
|
# Module container
|
5
5
|
class Modules < Array
|
6
|
-
# add module
|
6
|
+
# add module descendant.
|
7
7
|
#
|
8
8
|
# @param [String] module name
|
9
|
-
# @param [String]
|
10
|
-
def
|
9
|
+
# @param [String] descendant name
|
10
|
+
def add_module_descendant(module_name, descendant)
|
11
11
|
mod = find { |mod| mod.to_s == module_name }
|
12
|
-
mod.
|
12
|
+
mod.add_descendant(descendant) if mod
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
16
|
# Module info include module name and module spaces.
|
17
17
|
class Mod
|
18
|
-
attr_reader :
|
18
|
+
attr_reader :descendants
|
19
19
|
|
20
20
|
def initialize(module_name, modules)
|
21
21
|
@module_name = module_name
|
22
22
|
@modules = modules
|
23
|
-
@
|
23
|
+
@descendants = []
|
24
24
|
end
|
25
25
|
|
26
|
-
def
|
27
|
-
@
|
26
|
+
def add_descendant(descendant)
|
27
|
+
@descendants << descendant
|
28
28
|
end
|
29
29
|
|
30
30
|
def to_s
|
@@ -54,7 +54,7 @@ module RailsBestPractices
|
|
54
54
|
# restrict actions for inherited_resources
|
55
55
|
add_callback :start_command do |node|
|
56
56
|
if "include" == node.message.to_s
|
57
|
-
@helpers.
|
57
|
+
@helpers.add_module_descendant(node.arguments.all.first.to_s, current_class_name)
|
58
58
|
elsif @inherited_resources && "actions" == node.message.to_s
|
59
59
|
if "all" == node.arguments.all.first.to_s
|
60
60
|
@actions = DEFAULT_ACTIONS
|
@@ -87,9 +87,9 @@ module RailsBestPractices
|
|
87
87
|
|
88
88
|
# ask Reviews::RemoveUnusedMoethodsInHelperReview to check the controllers who include helpers.
|
89
89
|
add_callback :after_check do
|
90
|
-
|
91
|
-
if
|
92
|
-
Reviews::RemoveUnusedMethodsInHelpersReview.interesting_files *
|
90
|
+
descendants = @helpers.map(&:descendants).flatten
|
91
|
+
if descendants.present?
|
92
|
+
Reviews::RemoveUnusedMethodsInHelpersReview.interesting_files *descendants.map { |descendant| %r|#{descendant.underscore}| }
|
93
93
|
end
|
94
94
|
end
|
95
95
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module RailsBestPractices
|
3
|
+
module Reviews
|
4
|
+
# Review all code to make sure we either check the return value of "destroy"
|
5
|
+
# or use "destroy!"
|
6
|
+
#
|
7
|
+
# Review process:
|
8
|
+
# Track which nodes are used by 'if', 'unless', '&&' nodes etc. as we pass them by.
|
9
|
+
# Check all "save" calls to check the return value is used by a node we have visited.
|
10
|
+
class CheckDestroyReturnValueReview < Review
|
11
|
+
include Classable
|
12
|
+
interesting_nodes :call, :command_call, :method_add_arg, :if, :ifop, :elsif, :unless, :if_mod, :unless_mod, :assign, :binary
|
13
|
+
interesting_files ALL_FILES
|
14
|
+
|
15
|
+
add_callback :start_if, :start_ifop, :start_elsif, :start_unless, :start_if_mod, :start_unless_mod do |node|
|
16
|
+
@used_return_value_of = node.conditional_statement.all_conditions
|
17
|
+
end
|
18
|
+
|
19
|
+
add_callback :start_assign do |node|
|
20
|
+
@used_return_value_of = node.right_value
|
21
|
+
end
|
22
|
+
|
23
|
+
add_callback :start_binary do |node|
|
24
|
+
# Consider anything used in an expression like "A or B" as used
|
25
|
+
if %w(&& || and or).include?(node[2].to_s)
|
26
|
+
all_conditions = node.all_conditions
|
27
|
+
# if our current binary is a subset of the @used_return_value_of
|
28
|
+
# then don't overwrite it
|
29
|
+
already_included = @used_return_value_of &&
|
30
|
+
(all_conditions - @used_return_value_of).empty?
|
31
|
+
|
32
|
+
@used_return_value_of = node.all_conditions unless already_included
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def return_value_is_used? node
|
37
|
+
return false unless @used_return_value_of
|
38
|
+
node == @used_return_value_of or @used_return_value_of.include?(node)
|
39
|
+
end
|
40
|
+
|
41
|
+
def model_classnames
|
42
|
+
@model_classnames ||= models.map(&:to_s)
|
43
|
+
end
|
44
|
+
|
45
|
+
add_callback :start_call, :start_command_call, :start_method_add_arg do |node|
|
46
|
+
unless @already_checked == node
|
47
|
+
message = node.message.to_s
|
48
|
+
if message.eql? 'destroy'
|
49
|
+
unless return_value_is_used? node
|
50
|
+
add_error "check '#{message}' return value or use '#{message}!'"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
if node.sexp_type == :method_add_arg
|
54
|
+
@already_checked = node[1]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
module RailsBestPractices
|
3
3
|
module Reviews
|
4
|
-
# Review all code to make sure we either check the return value of "save"
|
5
|
-
# or use "save!"
|
4
|
+
# Review all code to make sure we either check the return value of "save", "update_attributes"
|
5
|
+
# and "create" or use "save!", "update_attributes!", or "create!", respectively.
|
6
6
|
#
|
7
7
|
# See the best practice details here http://rails-bestpractices.com/posts/2012/11/02/check-the-return-value-of-save-otherwise-use-save/
|
8
8
|
#
|
@@ -57,7 +57,7 @@ module RailsBestPractices
|
|
57
57
|
elsif message == 'create'
|
58
58
|
# We're only interested in 'create' calls on model classes:
|
59
59
|
possible_receiver_classes = [node.receiver.to_s] + classable_modules.map do |mod|
|
60
|
-
"#{mod}::#{node.receiver
|
60
|
+
"#{mod}::#{node.receiver}"
|
61
61
|
end
|
62
62
|
unless (possible_receiver_classes & model_classnames).empty?
|
63
63
|
add_error "use 'create!' instead of 'create' as the latter may not always save"
|
@@ -7,19 +7,19 @@ module RailsBestPractices
|
|
7
7
|
#
|
8
8
|
# Review process:
|
9
9
|
# remember all method calls in helpers.
|
10
|
-
# if they are not called in views or
|
10
|
+
# if they are not called in views, helpers, or controllers
|
11
11
|
# then they are unused methods in helpers.
|
12
12
|
class RemoveUnusedMethodsInHelpersReview < Review
|
13
13
|
include Moduleable
|
14
14
|
include Callable
|
15
15
|
include Exceptable
|
16
16
|
|
17
|
-
interesting_files HELPER_FILES, VIEW_FILES
|
17
|
+
interesting_files HELPER_FILES, VIEW_FILES, CONTROLLER_FILES
|
18
18
|
|
19
19
|
def initialize(options={})
|
20
20
|
super
|
21
21
|
@helper_methods = Prepares.helper_methods
|
22
|
-
self.class.interesting_files Prepares.helpers.map(&:
|
22
|
+
self.class.interesting_files Prepares.helpers.map(&:descendants)
|
23
23
|
end
|
24
24
|
|
25
25
|
# get all unused methods at the end of review process
|
data/lib/rails_best_practices/reviews/use_multipart_alternative_as_content_type_of_email_review.rb
CHANGED
@@ -45,6 +45,7 @@ module RailsBestPractices
|
|
45
45
|
# @param [String] name method name in action_mailer
|
46
46
|
def rails2_canonical_mailer_views?(name)
|
47
47
|
return true if mailer_files(name).length == 0
|
48
|
+
return true if mailer_files(name).none? { |filename| filename.index 'text.html' }
|
48
49
|
mailer_files(name).any? { |filename| filename.index 'text.html' } &&
|
49
50
|
mailer_files(name).any? { |filename| filename.index 'text.plain' }
|
50
51
|
end
|
@@ -54,6 +55,7 @@ module RailsBestPractices
|
|
54
55
|
# @param [String] name method name in action_mailer
|
55
56
|
def rails3_canonical_mailer_views?(name)
|
56
57
|
return true if mailer_files(name).length == 0
|
58
|
+
return true if mailer_files(name).none? { |filename| filename.index 'html' }
|
57
59
|
mailer_files(name).any? { |filename| filename.index 'html' } &&
|
58
60
|
mailer_files(name).any? { |filename| filename.index 'text' }
|
59
61
|
end
|
@@ -17,7 +17,6 @@ Gem::Specification.new do |s|
|
|
17
17
|
|
18
18
|
s.add_dependency("activesupport")
|
19
19
|
s.add_dependency("code_analyzer", ">= 0.4.3")
|
20
|
-
s.add_dependency("colored")
|
21
20
|
s.add_dependency("erubis")
|
22
21
|
s.add_dependency("i18n")
|
23
22
|
s.add_dependency("require_all")
|
@@ -30,6 +29,7 @@ Gem::Specification.new do |s|
|
|
30
29
|
s.add_development_dependency("slim")
|
31
30
|
s.add_development_dependency("bundler")
|
32
31
|
s.add_development_dependency("awesome_print")
|
32
|
+
s.add_development_dependency("rubocop", "= 0.30.1")
|
33
33
|
|
34
34
|
s.files = `git ls-files`.split("\n")
|
35
35
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|