rails_best_practices 1.7.2 → 1.8.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.
Files changed (32) hide show
  1. data/Gemfile.lock +1 -1
  2. data/README.md +5 -1
  3. data/lib/rails_best_practices/analyzer.rb +15 -1
  4. data/lib/rails_best_practices/command.rb +11 -1
  5. data/lib/rails_best_practices/core/check.rb +12 -5
  6. data/lib/rails_best_practices/core/error.rb +10 -6
  7. data/lib/rails_best_practices/core/model_associations.rb +16 -1
  8. data/lib/rails_best_practices/core/runner.rb +1 -0
  9. data/lib/rails_best_practices/core.rb +1 -0
  10. data/lib/rails_best_practices/core_ext/sexp.rb +6 -2
  11. data/lib/rails_best_practices/core_ext/string.rb +5 -0
  12. data/lib/rails_best_practices/prepares/model_prepare.rb +37 -2
  13. data/lib/rails_best_practices/prepares/route_prepare.rb +19 -3
  14. data/lib/rails_best_practices/reviews/always_add_db_index_review.rb +30 -0
  15. data/lib/rails_best_practices/reviews/not_use_time_ago_in_words_review.rb +30 -0
  16. data/lib/rails_best_practices/reviews/remove_unused_methods_in_controllers_review.rb +2 -1
  17. data/lib/rails_best_practices/reviews/remove_unused_methods_in_helpers_review.rb +1 -1
  18. data/lib/rails_best_practices/reviews/remove_unused_methods_in_models_review.rb +47 -5
  19. data/lib/rails_best_practices/reviews/restrict_auto_generated_routes_review.rb +2 -2
  20. data/lib/rails_best_practices/reviews.rb +1 -0
  21. data/lib/rails_best_practices/version.rb +1 -1
  22. data/rails_best_practices.gemspec +4 -0
  23. data/rails_best_practices.yml +1 -0
  24. data/spec/rails_best_practices/core/error_spec.rb +15 -3
  25. data/spec/rails_best_practices/core_ext/sexp_spec.rb +6 -1
  26. data/spec/rails_best_practices/prepares/helper_prepare_spec.rb +1 -1
  27. data/spec/rails_best_practices/prepares/model_prepare_spec.rb +40 -0
  28. data/spec/rails_best_practices/prepares/route_prepare_spec.rb +50 -0
  29. data/spec/rails_best_practices/reviews/always_add_db_index_review_spec.rb +72 -0
  30. data/spec/rails_best_practices/reviews/not_use_times_ago_in_words_review_spec.rb +49 -0
  31. data/spec/rails_best_practices/reviews/remove_unused_methods_in_models_review_spec.rb +64 -0
  32. metadata +32 -27
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rails_best_practices (1.7.2)
4
+ rails_best_practices (1.8.0)
5
5
  activesupport
6
6
  colored
7
7
  erubis
data/README.md CHANGED
@@ -3,7 +3,7 @@ rails_best_practices
3
3
 
4
4
  [![Build Status](https://secure.travis-ci.org/railsbp/rails_best_practices.png)](http://travis-ci.org/railsbp/rails_best_practices)
5
5
 
6
- [![Click here to lend your support to: rails-bestpractices.com and make a donation at www.pledgie.com !](https://www.pledgie.com/campaigns/12057.png?skin_name=chrome)](http://www.pledgie.com/campaigns/12057)
6
+ [![Click here to lend your support to: rails best practices and make a donation at www.pledgie.com !](http://www.pledgie.com/campaigns/12057.png?skin_name=chrome)](http://www.pledgie.com/campaigns/12057)
7
7
 
8
8
  rails_best_practices is a code metric tool to check the quality of rails codes.
9
9
 
@@ -50,6 +50,8 @@ By default rails_best_practices will do parse codes in vendor, spec, test and fe
50
50
  --features include features files
51
51
  -x, --exclude PATTERNS Don't analyze files matching a pattern
52
52
  (comma-separated regexp list)
53
+ -o, --only PATTERNS analyze files only matching a pattern
54
+ (comma-separated regexp list)
53
55
  -g, --generate Generate configuration yaml
54
56
  -v, --version Show this version
55
57
  -h, --help Show this message
@@ -140,6 +142,7 @@ Now you can customize this configuration file, the default configuration is as f
140
142
  RemoveUnusedMethodsInModelsCheck: { except_methods: [] }
141
143
  RemoveUnusedMethodsInControllersCheck: { except_methods: [] }
142
144
  RemoveUnusedMethodsInHelpersCheck: { except_methods: [] }
145
+ NotUseTimeAgoInWordsCheck: {}
143
146
 
144
147
  You can remove or comment one review to disable it, and you can change the options.
145
148
 
@@ -198,6 +201,7 @@ View
198
201
  3. Move code into helper
199
202
  4. Replace instance variable with local variable
200
203
  5. Simplify render in views
204
+ 6. Not use time_ago_in_words
201
205
 
202
206
  Deployment
203
207
 
@@ -46,6 +46,7 @@ module RailsBestPractices
46
46
  # @param [Hash] options
47
47
  def analyze
48
48
  @options["exclude"] ||= []
49
+ @options["only"] ||= []
49
50
  @options["output-file"] ||= "rails_best_practices_output.html"
50
51
 
51
52
  Core::Runner.base_path = @path
@@ -98,6 +99,10 @@ module RailsBestPractices
98
99
  files = expand_dirs_to_files(@path)
99
100
  files = file_sort(files)
100
101
 
102
+ if @options["only"].present?
103
+ files = file_accept(files, @options["only"])
104
+ end
105
+
101
106
  # By default, tmp, vender, spec, test, features are ignored.
102
107
  ["vendor", "spec", "test", "features", "tmp"].each do |pattern|
103
108
  files = file_ignore(files, "#{pattern}/") unless @options[pattern]
@@ -157,6 +162,14 @@ module RailsBestPractices
157
162
  files.reject { |file| file.index(pattern) }
158
163
  end
159
164
 
165
+ # accept specific files.
166
+ #
167
+ # @param [Array] files
168
+ # @param [Regexp] patterns, files match any pattern will be accepted
169
+ def file_accept files, patterns
170
+ files.reject { |file| !patterns.any? { |pattern| file =~ pattern } }
171
+ end
172
+
160
173
  # output errors on terminal.
161
174
  def output_terminal_errors
162
175
  @runner.errors.each { |error| plain_output(error.to_s, 'red') }
@@ -186,8 +199,9 @@ module RailsBestPractices
186
199
  # load git commit and git username info.
187
200
  def load_git_info
188
201
  git_progressbar = ProgressBar.new('Git Info', @runner.errors.size) if display_bar?
202
+ start = @runner.class.base_path =~ /\/$/ ? @runner.class.base_path.size : @runner.class.base_path.size + 1
189
203
  @runner.errors.each do |error|
190
- 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`
204
+ git_info = `cd #{@runner.class.base_path}; git blame -L #{error.line_number.split(',').first},+1 #{error.filename[start..-1]}`
191
205
  unless git_info == ""
192
206
  git_commit, git_username = git_info.split(/\d{4}-\d{2}-\d{2}/).first.split("(")
193
207
  error.git_commit = git_commit.split(" ").first.strip
@@ -19,6 +19,8 @@ require 'optparse'
19
19
  # --features include features files
20
20
  # -x, --exclude PATTERNS don't analyze files matching a pattern
21
21
  # (comma-separated regexp list)
22
+ # -o, --only PATTERNS analyze files only matching a pattern
23
+ # (comma-separated regexp list)
22
24
  # -g, --generate generate configuration yaml
23
25
  # -v, --version show this version
24
26
  # -h, --help show this message
@@ -94,12 +96,20 @@ OptionParser.new do |opts|
94
96
 
95
97
  opts.on("-x", "--exclude PATTERNS", "Don't analyze files matching a pattern", "(comma-separated regexp list)") do |list|
96
98
  begin
97
- options["exclude"] = list.split(/,/).map{|x| Regexp.new x}
99
+ options["exclude"] = list.split(",").map{|x| Regexp.new x}
98
100
  rescue RegexpError => e
99
101
  raise OptionParser::InvalidArgument, e.message
100
102
  end
101
103
  end
102
104
 
105
+ opts.on("-o", "--only PATTERNS", "Analyze files only matching a pattern", "(comma-separated regexp list)") do |list|
106
+ begin
107
+ options["only"] = list.split(",").map { |x| Regexp.new x }
108
+ rescue RegexpError => e
109
+ raise OptionParser::InvalidArgument e.message
110
+ end
111
+ end
112
+
103
113
  opts.on("-g", "--generate", "Generate configuration yaml") do
104
114
  options["generate"] = true
105
115
  end
@@ -73,10 +73,16 @@ module RailsBestPractices
73
73
  # add error if source code violates rails best practice.
74
74
  #
75
75
  # @param [String] message, is the string message for violation of the rails best practice
76
- # @param [String] file, is the filename of source code
77
- # @param [Integer] line, is the line number of the source code which is reviewing
78
- def add_error(message, file = @node.file, line = @node.line)
79
- errors << RailsBestPractices::Core::Error.new("#{file}", "#{line}", message, self.class.to_s, url)
76
+ # @param [String] filename, is the filename of source code
77
+ # @param [Integer] line_number, is the line number of the source code which is reviewing
78
+ def add_error(message, filename = @node.file, line_number = @node.line)
79
+ errors << RailsBestPractices::Core::Error.new(
80
+ :filename => filename,
81
+ :line_number => line_number,
82
+ :message => message,
83
+ :type => self.class.to_s,
84
+ :url => url
85
+ )
80
86
  end
81
87
 
82
88
  # errors that vialote the rails best practices.
@@ -265,7 +271,7 @@ module RailsBestPractices
265
271
  when "alias_method_chain"
266
272
  method, feature = *node.arguments.all.map(&:to_s)
267
273
  call_method("#{method}_with_#{feature}")
268
- when /(before|after)_/
274
+ when /^(before|after)_/
269
275
  node.arguments.all.each { |argument| mark_used(argument) }
270
276
  else
271
277
  mark_used(node.message)
@@ -374,6 +380,7 @@ module RailsBestPractices
374
380
  class_name, method_name = except_method.split('#')
375
381
  (class_name == '*' && method_name == method.method_name) ||
376
382
  (method_name == '*' && class_name == method.class_name) ||
383
+ (method_name == '*' && class_name == Prepares.klasses.find { |klass| klass.class_name == method.class_name }.try(:extend_class_name)) ||
377
384
  (class_name == method.class_name && method_name == method.method_name)
378
385
  end
379
386
  end
@@ -8,12 +8,16 @@ module RailsBestPractices
8
8
  attr_reader :filename, :line_number, :message, :type, :url
9
9
  attr_accessor :git_commit, :git_username, :hg_commit, :hg_username
10
10
 
11
- def initialize(filename, line_number, message, type, url = nil)
12
- @filename = filename
13
- @line_number = line_number
14
- @message = message
15
- @type = type
16
- @url = url
11
+ def initialize(options={})
12
+ @filename = options[:filename]
13
+ @line_number = options[:line_number].to_s
14
+ @message = options[:message]
15
+ @type = options[:type]
16
+ @url = options[:url]
17
+ @git_commit = options[:git_commit]
18
+ @git_username = options[:git_username]
19
+ @hg_commit = options[:hg_commit]
20
+ @hg_username = options[:hg_username]
17
21
  end
18
22
 
19
23
  def short_filename
@@ -7,7 +7,6 @@ module RailsBestPractices
7
7
  @associations = {}
8
8
  end
9
9
 
10
- # Add a model association.
11
10
  #
12
11
  # @param [String] model name
13
12
  # @param [String] association name
@@ -37,6 +36,22 @@ module RailsBestPractices
37
36
  associations = @associations[model_name]
38
37
  associations && associations[association_name]
39
38
  end
39
+
40
+ # delegate each to @associations.
41
+ def each(&block)
42
+ @associations.each { |model, model_associations| yield model, model_associations }
43
+ end
44
+
45
+ # Get association's class name
46
+ #
47
+ # @param [String] table name
48
+ # @param [String] association_name
49
+ # @return [String] association's class name
50
+ def get_association_class_name(table_name, association_name)
51
+ associations = @associations.select { |model, model_associations| model.table_name == table_name }.values.first and
52
+ association_meta = associations.select { |name, meta| name == association_name }.values.first and
53
+ association_meta["class_name"]
54
+ end
40
55
  end
41
56
  end
42
57
  end
@@ -3,6 +3,7 @@ require 'yaml'
3
3
  require 'ripper'
4
4
  require 'active_support/inflector'
5
5
  require 'active_support/core_ext/object/blank'
6
+ require 'active_support/core_ext/object/try'
6
7
 
7
8
  module RailsBestPractices
8
9
  module Core
@@ -15,6 +15,7 @@ require 'rails_best_practices/core/controllers'
15
15
  require 'rails_best_practices/core/helpers'
16
16
  require 'rails_best_practices/core/routes'
17
17
 
18
+ require 'rails_best_practices/core_ext/string'
18
19
  require 'rails_best_practices/core_ext/sexp'
19
20
  require 'rails_best_practices/core_ext/enumerable'
20
21
  require 'rails_best_practices/core_ext/erubis'
@@ -21,7 +21,7 @@ class Sexp
21
21
  # s(:@ident, "test", s(2, 12)
22
22
  # => 2
23
23
  def line
24
- if [:def, :command, :command_call, :call, :fcall, :method_add_arg, :method_add_block,
24
+ if [:def, :defs, :command, :command_call, :call, :fcall, :method_add_arg, :method_add_block,
25
25
  :var_ref, :const_ref, :const_path_ref, :class, :module, :if, :unless, :elsif, :binary,
26
26
  :alias, :symbol_literal, :symbol, :aref].include? sexp_type
27
27
  self[1].line
@@ -382,8 +382,12 @@ class Sexp
382
382
  #
383
383
  # @return [Sexp] method name node
384
384
  def method_name
385
- if :def == sexp_type
385
+ case sexp_type
386
+ when :def
386
387
  self[1]
388
+ when :defs
389
+ self[3]
390
+ else
387
391
  end
388
392
  end
389
393
 
@@ -0,0 +1,5 @@
1
+ class String
2
+ def table_name
3
+ self.gsub("::", "").tableize
4
+ end
5
+ end
@@ -7,8 +7,9 @@ module RailsBestPractices
7
7
  class ModelPrepare < Core::Check
8
8
  include Core::Check::Classable
9
9
  include Core::Check::Accessable
10
+ include Core::Check::Afterable
10
11
 
11
- interesting_nodes :class, :def, :command, :var_ref, :alias
12
+ interesting_nodes :class, :def, :defs, :command, :var_ref, :alias
12
13
  interesting_files MODEL_FILES
13
14
 
14
15
  ASSOCIATION_METHODS = %w(belongs_to has_one has_many has_and_belongs_to_many embeds_many embeds_one embedded_in many one)
@@ -27,7 +28,7 @@ module RailsBestPractices
27
28
  end
28
29
  end
29
30
 
30
- # check ref node to remember all methods.
31
+ # check def node to remember all methods.
31
32
  #
32
33
  # the remembered methods (@methods) are like
33
34
  # {
@@ -46,6 +47,25 @@ module RailsBestPractices
46
47
  end
47
48
  end
48
49
 
50
+ # check defs node to remember all static methods.
51
+ #
52
+ # the remembered methods (@methods) are like
53
+ # {
54
+ # "Post" => {
55
+ # "save" => {"file" => "app/models/post.rb", "line" => 10, "unused" => false, "unused" => false},
56
+ # "find" => {"file" => "app/models/post.rb", "line" => 10, "unused" => false, "unused" => false}
57
+ # },
58
+ # "Comment" => {
59
+ # "create" => {"file" => "app/models/comment.rb", "line" => 10, "unused" => false, "unused" => false},
60
+ # }
61
+ # }
62
+ def start_defs(node)
63
+ if @klass && "ActionMailer::Base" != current_extend_class_name
64
+ method_name = node.method_name.to_s
65
+ @methods.add_method(current_class_name, method_name, {"file" => node.file, "line" => node.line}, current_access_control)
66
+ end
67
+ end
68
+
49
69
  # check command node to remember all assoications or named_scope/scope methods.
50
70
  #
51
71
  # the remembered association names (@associations) are like
@@ -86,6 +106,21 @@ module RailsBestPractices
86
106
  @methods.add_method(current_class_name, method_name, {"file" => node.file, "line" => node.line}, current_access_control)
87
107
  end
88
108
 
109
+ # after prepare process, fix incorrect associations' class_name.
110
+ def after_prepare
111
+ @model_associations.each do |model, model_associations|
112
+ model_associations.each do |association_name, association_meta|
113
+ unless @models.include?(association_meta["class_name"])
114
+ if @models.include?("#{model}::#{association_meta['class_name']}")
115
+ association_meta["class_name"] = "#{model}::#{association_meta['class_name']}"
116
+ elsif @models.include?(model.gsub(/::\w+$/, ""))
117
+ association_meta["class_name"] = model.gsub(/::\w+$/, "")
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
123
+
89
124
  private
90
125
  # remember associations, with class to association names.
91
126
  def remember_association(node)
@@ -5,7 +5,7 @@ module RailsBestPractices
5
5
  module Prepares
6
6
  # Remembber routes.
7
7
  class RoutePrepare < Core::Check
8
- interesting_nodes :command, :command_call, :method_add_block
8
+ interesting_nodes :command, :command_call, :method_add_block, :do_block
9
9
  interesting_files ROUTE_FILES
10
10
 
11
11
  RESOURCES_ACTIONS = %w(index show new create edit update destroy)
@@ -14,6 +14,7 @@ module RailsBestPractices
14
14
  def initialize
15
15
  @routes = Prepares.routes
16
16
  @namespaces = []
17
+ @controller_names = []
17
18
  end
18
19
 
19
20
  # remember route for rails3.
@@ -25,7 +26,8 @@ module RailsBestPractices
25
26
  add_resource_routes(node)
26
27
  when "get", "post", "put", "delete"
27
28
  first_argument = node.arguments.all.first
28
- if current_controller_name.present?
29
+ second_argument = node.arguments.all[1]
30
+ if @controller_names.last
29
31
  action_name = first_argument.to_s
30
32
  @routes.add_route(current_namespaces, current_controller_name, action_name)
31
33
  else
@@ -34,6 +36,8 @@ module RailsBestPractices
34
36
  # do not parse redirect block
35
37
  return if :method_add_arg == route_node.sexp_type
36
38
  controller_name, action_name = route_node.to_s.split('#')
39
+ elsif :bare_assoc_hash == second_argument.try(:sexp_type) && second_argument.hash_value("to")
40
+ controller_name, action_name = second_argument.hash_value("to").to_s.split('#')
37
41
  else
38
42
  controller_name, action_name = first_argument.to_s.split('/')
39
43
  end
@@ -91,10 +95,12 @@ module RailsBestPractices
91
95
  case node.message.to_s
92
96
  when "namespace"
93
97
  @namespaces << node.arguments.all.first.to_s
98
+ @controller_name = nil
94
99
  when "scope"
95
100
  if node.arguments.all.last.hash_value("module").present?
96
101
  @namespaces << node.arguments.all.last.hash_value("module").to_s
97
102
  end
103
+ @controller_name = nil
98
104
  when "with_options"
99
105
  argument = node.arguments.all.last
100
106
  if :bare_assoc_hash == argument.sexp_type && argument.hash_value("controller").present?
@@ -119,6 +125,16 @@ module RailsBestPractices
119
125
  end
120
126
  end
121
127
 
128
+ # remember current controller name, used for nested resources.
129
+ def start_do_block(node)
130
+ @controller_names << @controller_name
131
+ end
132
+
133
+ # remove current controller name, and use upper lever resource name.
134
+ def end_do_block(node)
135
+ @controller_names.pop
136
+ end
137
+
122
138
  [:resources, :resource].each do |route_name|
123
139
  class_eval <<-EOF
124
140
  def add_#{route_name}_routes(node)
@@ -185,7 +201,7 @@ module RailsBestPractices
185
201
  end
186
202
 
187
203
  def current_controller_name
188
- @controller_name
204
+ @controller_names.last || @controller_name
189
205
  end
190
206
  end
191
207
  end
@@ -74,7 +74,9 @@ module RailsBestPractices
74
74
  # if there are any foreign keys not existed in index columns,
75
75
  # then we should add db index for that foreign keys.
76
76
  def after_review
77
+ remove_table_not_exist_foreign_keys
77
78
  remove_only_type_foreign_keys
79
+ combine_polymorphic_foreign_keys
78
80
  @foreign_keys.each do |table, foreign_key|
79
81
  table_node = @table_nodes[table]
80
82
  foreign_key.each do |column|
@@ -122,6 +124,18 @@ module RailsBestPractices
122
124
  end
123
125
  end
124
126
 
127
+ # remove the non foreign keys without corresponding tables.
128
+ def remove_table_not_exist_foreign_keys
129
+ @foreign_keys.each do |table, foreign_keys|
130
+ foreign_keys.delete_if do |key|
131
+ if key =~ /_id$/
132
+ class_name = Prepares.model_associations.get_association_class_name(table, key[0..-4])
133
+ class_name ? !@table_nodes[class_name.table_name] : !@table_nodes[key[0..-4].pluralize]
134
+ end
135
+ end
136
+ end
137
+ end
138
+
125
139
  # remove the non foreign keys with only _type column.
126
140
  def remove_only_type_foreign_keys
127
141
  @foreign_keys.each { |table, foreign_keys|
@@ -129,6 +143,22 @@ module RailsBestPractices
129
143
  }
130
144
  end
131
145
 
146
+ # combine polymorphic foreign keys, e.g.
147
+ # [tagger_id], [tagger_type] => [tagger_id, tagger_type]
148
+ def combine_polymorphic_foreign_keys
149
+ @index_columns.each { |table, foreign_keys|
150
+ foreign_id_keys = foreign_keys.select { |key| key.size == 1 && key.first =~ /_id/ }
151
+ foreign_type_keys = foreign_keys.select { |key| key.size == 1 && key.first =~ /_type/ }
152
+ foreign_id_keys.each do |id_key|
153
+ if type_key = foreign_type_keys.detect { |type_key| type_key.first == id_key.first.sub(/_id/, '') + "_type" }
154
+ foreign_keys.delete(id_key)
155
+ foreign_keys.delete(type_key)
156
+ foreign_keys << id_key + type_key
157
+ end
158
+ end
159
+ }
160
+ end
161
+
132
162
  # check if the table's column is indexed.
133
163
  def indexed?(table, column)
134
164
  index_columns = @index_columns[table]
@@ -0,0 +1,30 @@
1
+ # encoding: utf-8
2
+ require 'rails_best_practices/reviews/review'
3
+
4
+ module RailsBestPractices
5
+ module Reviews
6
+ # Review view and helper files to make sure not use time_ago_in_words or distance_of_time_in_words_to_now.
7
+ #
8
+ # See the best practice details here http://rails-bestpractices.com/posts/105-not-use-time_ago_in_words.
9
+ #
10
+ # Implementation:
11
+ #
12
+ # Review process:
13
+ # check all fcall node to see if its message is time_ago_in_words and distance_of_time_in_words_to_now
14
+ class NotUseTimeAgoInWordsReview < Review
15
+ interesting_nodes :fcall
16
+ interesting_files VIEW_FILES, HELPER_FILES
17
+
18
+ def url
19
+ "http://rails-bestpractices.com/posts/105-not-use-time_ago_in_words"
20
+ end
21
+
22
+ # check fcall node to see if its message is time_ago_in_words or distance_of_time_in_words_to_now
23
+ def start_fcall(node)
24
+ if "time_ago_in_words" == node.message.to_s || "distance_of_time_in_words_to_now" == node.message.to_s
25
+ add_error "not use time_ago_in_words"
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -98,7 +98,8 @@ module RailsBestPractices
98
98
  end
99
99
 
100
100
  def internal_except_methods
101
- %w(rescue_action).map { |method_name| "*\##{method_name}" }
101
+ %w(rescue_action).map { |method_name| "*\##{method_name}" } +
102
+ %w(Devise::OmniauthCallbacksController).map { |controller_name| "#{controller_name}#*" }
102
103
  end
103
104
 
104
105
  def mark_publicize(method_name, class_name=current_class_name)
@@ -40,7 +40,7 @@ module RailsBestPractices
40
40
  end
41
41
 
42
42
  def internal_except_methods
43
- []
43
+ ["*#url_for"]
44
44
  end
45
45
  end
46
46
  end
@@ -17,7 +17,7 @@ module RailsBestPractices
17
17
  include Callable
18
18
  include Exceptable
19
19
 
20
- interesting_nodes :command
20
+ interesting_nodes :command, :command_call, :method_add_arg
21
21
  interesting_files ALL_FILES
22
22
 
23
23
  def initialize(options={})
@@ -31,12 +31,50 @@ module RailsBestPractices
31
31
  end
32
32
 
33
33
  # mark validate methods as used.
34
+ # mark key method and value method for collection_select and grouped_collection_select.
34
35
  def start_command(node)
36
+ arguments = node.arguments.all
35
37
  case node.message.to_s
36
38
  when "validate", "validate_on_create", "validate_on_update"
37
- node.arguments.all.each { |argument| mark_used(argument) }
38
- else
39
- # nothing
39
+ arguments.each { |argument| mark_used(argument) }
40
+ when "collection_select"
41
+ mark_used(arguments[3])
42
+ mark_used(arguments[4])
43
+ when "grouped_collection_select"
44
+ mark_used(arguments[3])
45
+ mark_used(arguments[4])
46
+ mark_used(arguments[5])
47
+ mark_used(arguments[6])
48
+ end
49
+ end
50
+
51
+ # mark key method and value method for collection_select and grouped_collection_select.
52
+ def start_command_call(node)
53
+ arguments = node.arguments.all
54
+ case node.message.to_s
55
+ when "collection_select"
56
+ mark_used(arguments[2])
57
+ mark_used(arguments[3])
58
+ when "grouped_collection_select"
59
+ mark_used(arguments[2])
60
+ mark_used(arguments[3])
61
+ mark_used(arguments[4])
62
+ mark_used(arguments[5])
63
+ end
64
+ end
65
+
66
+ # mark key method and value method for options_from_collection_for_select and option_groups_from_collection_for_select.
67
+ def start_method_add_arg(node)
68
+ arguments = node.arguments.all
69
+ case node.message.to_s
70
+ when "options_from_collection_for_select"
71
+ mark_used(arguments[1])
72
+ mark_used(arguments[2])
73
+ when "option_groups_from_collection_for_select"
74
+ mark_used(arguments[1])
75
+ mark_used(arguments[2])
76
+ mark_used(arguments[3])
77
+ mark_used(arguments[4])
40
78
  end
41
79
  end
42
80
 
@@ -55,7 +93,11 @@ module RailsBestPractices
55
93
  end
56
94
 
57
95
  def internal_except_methods
58
- %w(initialize validate validate_each to_xml to_json assign_attributes after_find after_initialize).map { |method_name| "*\##{method_name}" }
96
+ %w(
97
+ initialize validate validate_each to_xml to_json assign_attributes after_find after_initialize
98
+ before_save before_create before_update before_destroy after_save after_create after_update after_destroy
99
+ to_param method_missing
100
+ ).map { |method_name| "*\##{method_name}" }
59
101
  end
60
102
  end
61
103
  end
@@ -86,10 +86,10 @@ module RailsBestPractices
86
86
  if hash_key_exist?(option_node,"controller")
87
87
  name = option_node.hash_value("controller").to_s
88
88
  else
89
- name = node.arguments.all.first.to_s.tableize
89
+ name = node.arguments.all.first.to_s.table_name
90
90
  end
91
91
  else
92
- name = node.arguments.all.first.to_s.tableize
92
+ name = node.arguments.all.first.to_s.table_name
93
93
  end
94
94
  namespaced_class_name(name)
95
95
  end
@@ -29,3 +29,4 @@ require 'rails_best_practices/reviews/restrict_auto_generated_routes_review'
29
29
  require 'rails_best_practices/reviews/remove_unused_methods_in_models_review'
30
30
  require 'rails_best_practices/reviews/remove_unused_methods_in_controllers_review'
31
31
  require 'rails_best_practices/reviews/remove_unused_methods_in_helpers_review'
32
+ require 'rails_best_practices/reviews/not_use_time_ago_in_words_review'
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module RailsBestPractices
3
- VERSION = "1.7.2"
3
+ VERSION = "1.8.0"
4
4
  end
@@ -40,6 +40,10 @@ Gem::Specification.new do |s|
40
40
 
41
41
  http://rails-bestpractices.com
42
42
 
43
+ Please also try our online service
44
+
45
+ https://railsbp.com
46
+
43
47
  Enjoy!
44
48
 
45
49
  Richard Huang (flyerhzm@gmail.com)
@@ -30,3 +30,4 @@ RestrictAutoGeneratedRoutesCheck: { }
30
30
  RemoveUnusedMethodsInModelsCheck: { except_methods: [] }
31
31
  RemoveUnusedMethodsInControllersCheck: { except_methods: [] }
32
32
  RemoveUnusedMethodsInHelpersCheck: { except_methods: [] }
33
+ NotUseTimeAgoInWordsCheck: { }
@@ -2,15 +2,27 @@ require 'spec_helper'
2
2
 
3
3
  describe RailsBestPractices::Core::Error do
4
4
  it "should return error with filename, line number and message" do
5
- RailsBestPractices::Core::Error.new("app/models/user.rb", "100", "not good", "BogusReview").to_s.should == "app/models/user.rb:100 - not good"
5
+ RailsBestPractices::Core::Error.new(
6
+ :filename => "app/models/user.rb",
7
+ :line_number => "100",
8
+ :message => "not good",
9
+ :type => "BogusReview").to_s.should == "app/models/user.rb:100 - not good"
6
10
  end
7
11
 
8
12
  it "should return short filename" do
9
13
  RailsBestPractices::Core::Runner.base_path = "../rails-bestpractices.com"
10
- RailsBestPractices::Core::Error.new("../rails-bestpractices.com/app/models/user.rb", "100", "not good", "BogusReview").short_filename.should == "app/models/user.rb"
14
+ RailsBestPractices::Core::Error.new(
15
+ :filename => "../rails-bestpractices.com/app/models/user.rb",
16
+ :line_number => "100",
17
+ :message => "not good",
18
+ :type => "BogusReview").short_filename.should == "app/models/user.rb"
11
19
  end
12
20
 
13
21
  it "should return first line number" do
14
- RailsBestPractices::Core::Error.new("app/models/user.rb", "50,70,100", "not good", "BogusReview").first_line_number.should == "50"
22
+ RailsBestPractices::Core::Error.new(
23
+ :filename => "app/models/user.rb",
24
+ :line_number => "50,70,100",
25
+ :message => "not good",
26
+ :type => "BogusReview").first_line_number.should == "50"
15
27
  end
16
28
  end
@@ -281,10 +281,15 @@ describe Sexp do
281
281
  end
282
282
 
283
283
  describe "method_name" do
284
- it "should get the method name of defn" do
284
+ it "should get the method name of def" do
285
285
  node = parse_content("def show; end").grep_node(:sexp_type => :def)
286
286
  node.method_name.to_s.should == "show"
287
287
  end
288
+
289
+ it "should get the method name of defs" do
290
+ node = parse_content("def self.find; end").grep_node(:sexp_type => :defs)
291
+ node.method_name.to_s.should == "find"
292
+ end
288
293
  end
289
294
 
290
295
  describe "body" do
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe RailsBestPractices::Prepares::HelperPrepare do
4
- let(:runner) { RailsBestPractices::Core::Runner.new(:parepare => RailsBestPractices::Prepares::HelperPrepare.new) }
4
+ let(:runner) { RailsBestPractices::Core::Runner.new(:prepares => RailsBestPractices::Prepares::HelperPrepare.new) }
5
5
 
6
6
  context "methods" do
7
7
  it "should parse helper methods" do
@@ -93,6 +93,46 @@ describe RailsBestPractices::Prepares::ModelPrepare do
93
93
  model_associations = RailsBestPractices::Prepares.model_associations
94
94
  model_associations.get_association("Citizen", "nations").should == {"meta" => "has_and_belongs_to_many", "class_name" => "Country"}
95
95
  end
96
+
97
+ context "namespace" do
98
+ it "should parse with namespace" do
99
+ content =<<-EOF
100
+ class Community < ActiveRecord::Base
101
+ has_many :members
102
+ end
103
+ EOF
104
+ runner.prepare("app/models/community.rb", content)
105
+ content =<<-EOF
106
+ class Community::Member < ActiveRecord::Base
107
+ belongs_to :community
108
+ end
109
+ EOF
110
+ runner.prepare("app/models/community/member.rb", content)
111
+ runner.after_prepare
112
+ model_associations = RailsBestPractices::Prepares.model_associations
113
+ model_associations.get_association("Community", "members").should == {"meta" => "has_many", "class_name" => "Community::Member"}
114
+ model_associations.get_association("Community::Member", "community").should == {"meta" => "belongs_to", "class_name" => "Community"}
115
+ end
116
+
117
+ it "should parse without namespace" do
118
+ content =<<-EOF
119
+ class Community::Member::Rating < ActiveRecord::Base
120
+ belongs_to :member
121
+ end
122
+ EOF
123
+ runner.prepare("app/models/community/member/rating.rb", content)
124
+ content =<<-EOF
125
+ class Community::Member < ActiveRecord::Base
126
+ has_many :ratings
127
+ end
128
+ EOF
129
+ runner.prepare("app/models/community/member.rb", content)
130
+ runner.after_prepare
131
+ model_associations = RailsBestPractices::Prepares.model_associations
132
+ model_associations.get_association("Community::Member::Rating", "member").should == {"meta" => "belongs_to", "class_name" => "Community::Member"}
133
+ model_associations.get_association("Community::Member", "ratings").should == {"meta" => "has_many", "class_name" => "Community::Member::Rating"}
134
+ end
135
+ end
96
136
  end
97
137
 
98
138
  context "mongoid embeds" do
@@ -255,6 +255,18 @@ describe RailsBestPractices::Prepares::RoutePrepare do
255
255
  routes = RailsBestPractices::Prepares.routes
256
256
  routes.map(&:to_s).should == ["AdminSessionController#new"]
257
257
  end
258
+
259
+ it "should not take former resources for direct get/post" do
260
+ content =<<-EOF
261
+ ActionController::Routing::Routes.draw do |map|
262
+ map.resources :posts
263
+ map.stop 'sprints/stop', :controller => 'sprints', :action => 'stop'
264
+ end
265
+ EOF
266
+ runner.prepare('config/routes.rb', content)
267
+ routes = RailsBestPractices::Prepares.routes
268
+ routes.last.to_s.should == "SprintsController#stop"
269
+ end
258
270
  end
259
271
 
260
272
  context "rails3" do
@@ -517,6 +529,18 @@ describe RailsBestPractices::Prepares::RoutePrepare do
517
529
  routes.map(&:to_s).should == ["PostsController#show", "PostsController#create", "PostsController#update", "PostsController#destroy", "HighVoltage::PagesController#show"]
518
530
  end
519
531
 
532
+ it "should add routes for another get/post" do
533
+ content =<<-EOF
534
+ RailsBestPracticesCom::Application.routes.draw do
535
+ get "/login", to: 'sessions#new', as: :login
536
+ end
537
+ EOF
538
+ runner.prepare('config/routes.rb', content)
539
+ routes = RailsBestPractices::Prepares.routes
540
+ routes.size.should == 1
541
+ routes.first.to_s.should == "SessionsController#new"
542
+ end
543
+
520
544
  it "should add match route" do
521
545
  content =<<-EOF
522
546
  RailsBestPracticesCom::Application.routes.draw do
@@ -572,5 +596,31 @@ describe RailsBestPractices::Prepares::RoutePrepare do
572
596
  routes = RailsBestPractices::Prepares.routes
573
597
  routes.size.should == 0
574
598
  end
599
+
600
+ it "should parse customize route in nested resources" do
601
+ content =<<-EOF
602
+ RailsBestPracticesCom::Application.routes.draw do
603
+ resources :posts do
604
+ resources :comments
605
+ post :stop
606
+ end
607
+ end
608
+ EOF
609
+ runner.prepare('config/routes.rb', content)
610
+ routes = RailsBestPractices::Prepares.routes
611
+ routes.last.to_s.should == "PostsController#stop"
612
+ end
613
+
614
+ it "should not take former resources for direct get/post" do
615
+ content =<<-EOF
616
+ RailsBestPracticesCom::Application.routes.draw do
617
+ resources :posts
618
+ post "sprints/stop"
619
+ end
620
+ EOF
621
+ runner.prepare('config/routes.rb', content)
622
+ routes = RailsBestPractices::Prepares.routes
623
+ routes.last.to_s.should == "SprintsController#stop"
624
+ end
575
625
  end
576
626
  end
@@ -13,6 +13,10 @@ describe RailsBestPractices::Reviews::AlwaysAddDbIndexReview do
13
13
  t.integer "post_id"
14
14
  t.integer "user_id"
15
15
  end
16
+ create_table "posts", :force => true do |t|
17
+ end
18
+ create_table "users", :force => true do |t|
19
+ end
16
20
  end
17
21
  EOF
18
22
  runner.review('db/schema.rb', content)
@@ -62,6 +66,8 @@ describe RailsBestPractices::Reviews::AlwaysAddDbIndexReview do
62
66
  t.integer "taggable_id"
63
67
  t.string "taggable_type"
64
68
  end
69
+ create_table "tags", :force => true do |t|
70
+ end
65
71
 
66
72
  add_index "taggings", ["tag_id"], :name => "index_taggings_on_tag_id"
67
73
  end
@@ -80,6 +86,8 @@ describe RailsBestPractices::Reviews::AlwaysAddDbIndexReview do
80
86
  t.integer "taggable_id"
81
87
  t.string "taggable_type"
82
88
  end
89
+ create_table "tags", :force => true do |t|
90
+ end
83
91
 
84
92
  add_index "taggings", ["taggable_id", "taggable_type"], :name => "index_taggings_on_taggable_id_and_taggable_type"
85
93
  end
@@ -99,6 +107,8 @@ describe RailsBestPractices::Reviews::AlwaysAddDbIndexReview do
99
107
  t.integer "icon_file_size"
100
108
  t.string "icon_content_type"
101
109
  end
110
+ create_table "users", :force => true do |t|
111
+ end
102
112
  end
103
113
  EOF
104
114
  runner.review('db/schema.rb', content)
@@ -129,6 +139,10 @@ describe RailsBestPractices::Reviews::AlwaysAddDbIndexReview do
129
139
  t.integer "post_id"
130
140
  t.integer "user_id"
131
141
  end
142
+ create_table "posts", :force => true do |t|
143
+ end
144
+ create_table "users", :force => true do |t|
145
+ end
132
146
 
133
147
  add_index "comments", ["post_id"], :name => "index_comments_on_post_id"
134
148
  add_index "comments", ["user_id"], :name => "index_comments_on_user_id"
@@ -185,4 +199,62 @@ describe RailsBestPractices::Reviews::AlwaysAddDbIndexReview do
185
199
  runner.after_review
186
200
  runner.should have(0).errors
187
201
  end
202
+
203
+ it "should not always add db index if two indexes for polymorphic association" do
204
+ content =<<-EOF
205
+ ActiveRecord::Schema.define(:version => 20100603080629) do
206
+ create_table "taggings", :force => true do |t|
207
+ t.integer "tagger_id"
208
+ t.string "tagger_type"
209
+ t.datetime "created_at"
210
+ end
211
+
212
+ add_index "taggings", ["tagger_id"], :name => "index_taggings_on_tagger_id"
213
+ add_index "taggings", ["tagger_type"], :name => "index_taggings_on_tagger_type"
214
+ end
215
+ EOF
216
+ runner.review('db/schema.rb', content)
217
+ runner.after_review
218
+ runner.should have(0).errors
219
+ end
220
+
221
+ it "should not always add db index if table does not exist" do
222
+ content =<<-EOF
223
+ ActiveRecord::Schema.define(:version => 20100603080629) do
224
+ create_table "comments", :force => true do |t|
225
+ t.integer "post_id"
226
+ end
227
+ end
228
+ EOF
229
+ runner.review('db/schema.rb', content)
230
+ runner.after_review
231
+ runner.should have(0).errors
232
+ end
233
+
234
+ it "should always add db index if association_name is different to foreign_key" do
235
+ content =<<-EOF
236
+ class Comment < ActiveRecord::Base
237
+ belongs_to :commentor, :class_name => "User"
238
+ end
239
+ EOF
240
+ runner.prepare('app/models/comment.rb', content)
241
+ content =<<-EOF
242
+ class User < ActiveRecord::Base
243
+ end
244
+ EOF
245
+ runner.prepare('app/models/user.rb', content)
246
+ content =<<-EOF
247
+ ActiveRecord::Schema.define(:version => 20100603080629) do
248
+ create_table "comments", :force => true do |t|
249
+ t.integer "commentor_id"
250
+ end
251
+ create_table "users", :force => true do |t|
252
+ end
253
+ end
254
+ EOF
255
+ runner.review('db/schema.rb', content)
256
+ runner.after_review
257
+ runner.should have(1).errors
258
+ runner.errors[0].to_s.should == "db/schema.rb:2 - always add db index (comments => [commentor_id])"
259
+ end
188
260
  end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ describe RailsBestPractices::Reviews::NotUseTimeAgoInWordsReview do
4
+ let(:runner) { RailsBestPractices::Core::Runner.new(:reviews => RailsBestPractices::Reviews::NotUseTimeAgoInWordsReview.new) }
5
+
6
+ describe "time_ago_in_words" do
7
+ it "should not use in views" do
8
+ content =<<-EOF
9
+ <%= time_ago_in_words(post.created_at) %>
10
+ EOF
11
+ runner.review('app/views/posts/show.html.erb', content)
12
+ runner.should have(1).errors
13
+ runner.errors[0].to_s.should == "app/views/posts/show.html.erb:1 - not use time_ago_in_words"
14
+ end
15
+
16
+ it "should not use in helpers" do
17
+ content =<<-EOF
18
+ def timeago
19
+ content_tag(:p, time_ago_in_words(post.created_at))
20
+ end
21
+ EOF
22
+ runner.review('app/helpers/posts_helper.rb', content)
23
+ runner.should have(1).errors
24
+ runner.errors[0].to_s.should == "app/helpers/posts_helper.rb:2 - not use time_ago_in_words"
25
+ end
26
+ end
27
+
28
+ describe "distance_of_time_in_words_to_now" do
29
+ it "should not use in views" do
30
+ content =<<-EOF
31
+ <%= distance_of_time_in_words_to_now(post.created_at) %>
32
+ EOF
33
+ runner.review('app/views/posts/show.html.erb', content)
34
+ runner.should have(1).errors
35
+ runner.errors[0].to_s.should == "app/views/posts/show.html.erb:1 - not use time_ago_in_words"
36
+ end
37
+
38
+ it "should not use in helpers" do
39
+ content =<<-EOF
40
+ def timeago
41
+ content_tag(:p, distance_of_time_in_words_to_now(post.created_at))
42
+ end
43
+ EOF
44
+ runner.review('app/helpers/posts_helper.rb', content)
45
+ runner.should have(1).errors
46
+ runner.errors[0].to_s.should == "app/helpers/posts_helper.rb:2 - not use time_ago_in_words"
47
+ end
48
+ end
49
+ end
@@ -602,5 +602,69 @@ describe RailsBestPractices::Reviews::RemoveUnusedMethodsInModelsReview do
602
602
  runner.after_review
603
603
  runner.should have(0).errors
604
604
  end
605
+
606
+ it "should not remove unused methods for to_param" do
607
+ content =<<-EOF
608
+ class Post < ActiveRecord::Base
609
+ def to_param
610
+ id
611
+ end
612
+ end
613
+ EOF
614
+ runner.prepare("app/models/post.rb", content)
615
+ runner.review("app/models/post.rb", content)
616
+ runner.after_review
617
+ runner.should have(0).errors
618
+ end
619
+ end
620
+
621
+ context "helper method" do
622
+ it "should not remove unused method for coommand_call collection_select" do
623
+ content =<<-EOF
624
+ class Category < ActiveRecord::Base
625
+ def indented_name; end
626
+ end
627
+ EOF
628
+ runner.prepare("app/models/category.rb", content)
629
+ runner.review("app/models/category.rb", content)
630
+ content =<<-EOF
631
+ <%= f.collection_select :parent_id, Category.all_hierarchic(except: @category), :id, :indented_name, {include_blank: true} %>
632
+ EOF
633
+ runner.review("app/views/categories/_form.html.erb", content)
634
+ runner.after_review
635
+ runner.should have(0).errors
636
+ end
637
+
638
+ it "should not remove unused method for command collection_select" do
639
+ content =<<-EOF
640
+ class Category < ActiveRecord::Base
641
+ def indented_name; end
642
+ end
643
+ EOF
644
+ runner.prepare("app/models/category.rb", content)
645
+ runner.review("app/models/category.rb", content)
646
+ content =<<-EOF
647
+ <%= collection_select :category, :parent_id, Category.all_hierarchic(except: @category), :id, :indented_name, {include_blank: true} %>
648
+ EOF
649
+ runner.review("app/views/categories/_form.html.erb", content)
650
+ runner.after_review
651
+ runner.should have(0).errors
652
+ end
653
+
654
+ it "should not remove unused method for options_from_collection_for_select" do
655
+ content =<<-EOF
656
+ class Category < ActiveRecord::Base
657
+ def indented_name; end
658
+ end
659
+ EOF
660
+ runner.prepare("app/models/category.rb", content)
661
+ runner.review("app/models/category.rb", content)
662
+ content =<<-EOF
663
+ <%= select_tag 'category', options_from_collection_for_select(Category.all_hierachic(except: @category), :id, :indented_name) %>
664
+ EOF
665
+ runner.review("app/views/categories/_form.html.erb", content)
666
+ runner.after_review
667
+ runner.should have(0).errors
668
+ end
605
669
  end
606
670
  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.7.2
4
+ version: 1.8.0
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-12-28 00:00:00.000000000Z
12
+ date: 2012-02-24 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sexp_processor
16
- requirement: &70233747842020 !ruby/object:Gem::Requirement
16
+ requirement: &70270463469100 !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: *70233747842020
24
+ version_requirements: *70270463469100
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: progressbar
27
- requirement: &70233747840780 !ruby/object:Gem::Requirement
27
+ requirement: &70270463467440 !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: *70233747840780
35
+ version_requirements: *70270463467440
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: colored
38
- requirement: &70233747835040 !ruby/object:Gem::Requirement
38
+ requirement: &70270463456860 !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: *70233747835040
46
+ version_requirements: *70270463456860
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: erubis
49
- requirement: &70233747833880 !ruby/object:Gem::Requirement
49
+ requirement: &70270463455020 !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: *70233747833880
57
+ version_requirements: *70270463455020
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: i18n
60
- requirement: &70233747832640 !ruby/object:Gem::Requirement
60
+ requirement: &70270463453880 !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: *70233747832640
68
+ version_requirements: *70270463453880
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: activesupport
71
- requirement: &70233747831960 !ruby/object:Gem::Requirement
71
+ requirement: &70270463452620 !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: *70233747831960
79
+ version_requirements: *70270463452620
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: rake
82
- requirement: &70233747831080 !ruby/object:Gem::Requirement
82
+ requirement: &70270463451560 !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: *70233747831080
90
+ version_requirements: *70270463451560
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: rspec
93
- requirement: &70233747830280 !ruby/object:Gem::Requirement
93
+ requirement: &70270463450820 !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: *70233747830280
101
+ version_requirements: *70270463450820
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: haml
104
- requirement: &70233747829320 !ruby/object:Gem::Requirement
104
+ requirement: &70270463450120 !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: *70233747829320
112
+ version_requirements: *70270463450120
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: slim
115
- requirement: &70233747828460 !ruby/object:Gem::Requirement
115
+ requirement: &70270463444400 !ruby/object:Gem::Requirement
116
116
  none: false
117
117
  requirements:
118
118
  - - ! '>='
@@ -120,10 +120,10 @@ dependencies:
120
120
  version: '0'
121
121
  type: :development
122
122
  prerelease: false
123
- version_requirements: *70233747828460
123
+ version_requirements: *70270463444400
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: bundler
126
- requirement: &70233747827520 !ruby/object:Gem::Requirement
126
+ requirement: &70270463443380 !ruby/object:Gem::Requirement
127
127
  none: false
128
128
  requirements:
129
129
  - - ! '>='
@@ -131,7 +131,7 @@ dependencies:
131
131
  version: '0'
132
132
  type: :development
133
133
  prerelease: false
134
- version_requirements: *70233747827520
134
+ version_requirements: *70270463443380
135
135
  description: a code metric tool for rails codes, written in Ruby.
136
136
  email:
137
137
  - flyerhzm@gmail.com
@@ -179,6 +179,7 @@ files:
179
179
  - lib/rails_best_practices/core_ext/enumerable.rb
180
180
  - lib/rails_best_practices/core_ext/erubis.rb
181
181
  - lib/rails_best_practices/core_ext/sexp.rb
182
+ - lib/rails_best_practices/core_ext/string.rb
182
183
  - lib/rails_best_practices/lexicals.rb
183
184
  - lib/rails_best_practices/lexicals/remove_tab_check.rb
184
185
  - lib/rails_best_practices/lexicals/remove_trailing_whitespace_check.rb
@@ -203,6 +204,7 @@ files:
203
204
  - lib/rails_best_practices/reviews/move_model_logic_into_model_review.rb
204
205
  - lib/rails_best_practices/reviews/needless_deep_nesting_review.rb
205
206
  - lib/rails_best_practices/reviews/not_use_default_route_review.rb
207
+ - lib/rails_best_practices/reviews/not_use_time_ago_in_words_review.rb
206
208
  - lib/rails_best_practices/reviews/overuse_route_customizations_review.rb
207
209
  - lib/rails_best_practices/reviews/remove_empty_helpers_review.rb
208
210
  - lib/rails_best_practices/reviews/remove_unused_methods_in_controllers_review.rb
@@ -266,6 +268,7 @@ files:
266
268
  - spec/rails_best_practices/reviews/move_model_logic_into_model_review_spec.rb
267
269
  - spec/rails_best_practices/reviews/needless_deep_nesting_review_spec.rb
268
270
  - spec/rails_best_practices/reviews/not_use_default_route_review_spec.rb
271
+ - spec/rails_best_practices/reviews/not_use_times_ago_in_words_review_spec.rb
269
272
  - spec/rails_best_practices/reviews/overuse_route_customizations_review_spec.rb
270
273
  - spec/rails_best_practices/reviews/remove_empty_helpers_review_spec.rb
271
274
  - spec/rails_best_practices/reviews/remove_unused_methods_in_controllers_review_spec.rb
@@ -289,7 +292,8 @@ licenses: []
289
292
  post_install_message: ! "********************************************************************************\n\n
290
293
  \ rails_best_practices is a code metric tool to check the quality of rails codes.\n\n
291
294
  \ I highly recommend you browse the Rails Best Practices website first.\n\n http://rails-bestpractices.com\n\n
292
- \ Enjoy!\n\n Richard Huang (flyerhzm@gmail.com)\n\n********************************************************************************\n"
295
+ \ Please also try our online service\n\n https://railsbp.com\n\n Enjoy!\n\n
296
+ \ Richard Huang (flyerhzm@gmail.com)\n\n********************************************************************************\n"
293
297
  rdoc_options: []
294
298
  require_paths:
295
299
  - lib
@@ -302,7 +306,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
302
306
  version: '0'
303
307
  segments:
304
308
  - 0
305
- hash: 539864756318375074
309
+ hash: 920336894600409116
306
310
  required_rubygems_version: !ruby/object:Gem::Requirement
307
311
  none: false
308
312
  requirements:
@@ -311,7 +315,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
311
315
  version: 1.3.6
312
316
  requirements: []
313
317
  rubyforge_project:
314
- rubygems_version: 1.8.10
318
+ rubygems_version: 1.8.15
315
319
  signing_key:
316
320
  specification_version: 3
317
321
  summary: a code metric tool for rails codes.
@@ -357,6 +361,7 @@ test_files:
357
361
  - spec/rails_best_practices/reviews/move_model_logic_into_model_review_spec.rb
358
362
  - spec/rails_best_practices/reviews/needless_deep_nesting_review_spec.rb
359
363
  - spec/rails_best_practices/reviews/not_use_default_route_review_spec.rb
364
+ - spec/rails_best_practices/reviews/not_use_times_ago_in_words_review_spec.rb
360
365
  - spec/rails_best_practices/reviews/overuse_route_customizations_review_spec.rb
361
366
  - spec/rails_best_practices/reviews/remove_empty_helpers_review_spec.rb
362
367
  - spec/rails_best_practices/reviews/remove_unused_methods_in_controllers_review_spec.rb