rails_best_practices 1.15.7 → 1.16.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -7,22 +7,22 @@
7
7
  [![Coderwall Endorse](http://api.coderwall.com/flyerhzm/endorsecount.png)](http://coderwall.com/flyerhzm)
8
8
  [![Click here to lend your support to: rails best practices and make a donation at www.pledgie.com !](https://pledgie.com/campaigns/12057.png?skin_name=chrome)](https://pledgie.com/campaigns/12057)
9
9
 
10
- rails_best_practices is a code metric tool to check the quality of rails code.
10
+ rails_best_practices is a code metric tool to check the quality of Rails code.
11
11
 
12
- it supports following ORM/ODMs:
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 works well only in ruby 1.9.3, 2.0.0, and 2.1.0 so far. It is incompatible with ruby 1.8.
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 rails app
35
+ At the root directory of a Rails app, run:
36
36
 
37
37
  rails_best_practices .
38
38
 
39
- or html output
39
+ Or for HTML output:
40
40
 
41
41
  rails_best_practices -f html .
42
42
 
43
- By default rails_best_practices will do parse codes in vendor, spec, test and features directories.
43
+ By default rails_best_practices will parse code in the `vendor`, `spec`, `test` and `features` directories.
44
44
 
45
- ### Excluding folders
45
+ ### Excluding directories
46
46
 
47
- To exclude folder simply call it with -e or --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 folders, separate them with comma
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 line options
55
+ ### Other command-line options
56
56
 
57
- To see full list of commandline options call:
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
- Github: <http://github.com/railsbp/rails_best_practices>
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 in Gemfile
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
- ## Issue
116
+ ## Issues
119
117
 
120
- If you install the rails_best_practices with bundler-installed github-sourced gem, please use the following command instead.
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 got NoMethodError or any syntax error, you should use debug mode to detect which file rails_best_practices is parsing and getting the error.
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
- Then give me the error stack and the source code of the file that rails_best_practices is parsing error.
126
+ That will provide the error's stack trace and the source code of the file which is causing the error.
129
127
 
130
- ## Customize Configuration
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, the default configuration is as follows:
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 one review to disable it, and you can change the options.
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. the law of demeter
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 db index
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 capistrano
250
- 2. Speed up assets precompile with turbo-sprockets-rails3
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 def (disabled by default)
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 Check List
259
+ ## Write Your Own Checklist
262
260
 
263
- If you want to write your own check list (some check list only for your rails projects), please read this first, [How to write your own check list?][1]
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 rails consulting services, you can contact us by twitter or email.
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
- task :default => :spec
18
+ RuboCop::RakeTask.new
19
+
20
+ task :default => [:spec, :rubocop]
18
21
  task :test => :spec
@@ -2,6 +2,7 @@
2
2
  require 'code_analyzer'
3
3
  require 'require_all'
4
4
  require 'rails_best_practices/core'
5
+ require 'rails_best_practices/colorize'
5
6
  require 'rails_best_practices/analyzer'
6
7
  require 'rails_best_practices/lexicals'
7
8
  require 'rails_best_practices/prepares'
@@ -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 message.send(color)
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 Codes', :total => parse_files.size * 3) if display_bar?
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
@@ -0,0 +1,11 @@
1
+ module RailsBestPractices
2
+ class Colorize
3
+ def self.red(message)
4
+ "\e[31m#{message}\e[0m"
5
+ end
6
+
7
+ def self.green(message)
8
+ "\e[32m#{message}\e[0m"
9
+ end
10
+ end
11
+ end
@@ -3,28 +3,28 @@ module RailsBestPractices
3
3
  module Core
4
4
  # Module container
5
5
  class Modules < Array
6
- # add module decendant.
6
+ # add module descendant.
7
7
  #
8
8
  # @param [String] module name
9
- # @param [String] decendant name
10
- def add_module_decendant(module_name, decendant)
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.add_decendant(decendant) if 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 :decendants
18
+ attr_reader :descendants
19
19
 
20
20
  def initialize(module_name, modules)
21
21
  @module_name = module_name
22
22
  @modules = modules
23
- @decendants = []
23
+ @descendants = []
24
24
  end
25
25
 
26
- def add_decendant(decendant)
27
- @decendants << decendant
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.add_module_decendant(node.arguments.all.first.to_s, current_class_name)
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
- decendants = @helpers.map(&:decendants).flatten
91
- if decendants.present?
92
- Reviews::RemoveUnusedMethodsInHelpersReview.interesting_files *decendants.map { |decendant| %r|#{decendant.underscore}| }
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.to_s}"
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 helpers,
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(&:decendants)
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
@@ -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
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module RailsBestPractices
3
- VERSION = "1.15.7"
3
+ VERSION = "1.16.0"
4
4
  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")