rails_best_practices 1.19.3 → 1.21.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 (153) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +0 -1
  3. data/.travis.yml +2 -3
  4. data/CHANGELOG.md +10 -11
  5. data/Gemfile +3 -5
  6. data/Gemfile.lock +125 -0
  7. data/Guardfile +2 -0
  8. data/README.md +5 -1
  9. data/Rakefile +2 -17
  10. data/assets/result.html.erb +2 -0
  11. data/lib/rails_best_practices.rb +4 -2
  12. data/lib/rails_best_practices/analyzer.rb +63 -51
  13. data/lib/rails_best_practices/cli.rb +22 -0
  14. data/lib/rails_best_practices/command.rb +1 -131
  15. data/lib/rails_best_practices/core/check.rb +63 -55
  16. data/lib/rails_best_practices/core/checks_loader.rb +24 -23
  17. data/lib/rails_best_practices/core/configs.rb +1 -2
  18. data/lib/rails_best_practices/core/controllers.rb +1 -2
  19. data/lib/rails_best_practices/core/error.rb +1 -1
  20. data/lib/rails_best_practices/core/helpers.rb +1 -2
  21. data/lib/rails_best_practices/core/mailers.rb +1 -2
  22. data/lib/rails_best_practices/core/methods.rb +27 -21
  23. data/lib/rails_best_practices/core/model_associations.rb +10 -5
  24. data/lib/rails_best_practices/core/models.rb +1 -2
  25. data/lib/rails_best_practices/core/modules.rb +1 -1
  26. data/lib/rails_best_practices/core/routes.rb +2 -2
  27. data/lib/rails_best_practices/core/runner.rb +87 -72
  28. data/lib/rails_best_practices/inline_disables.rb +3 -0
  29. data/lib/rails_best_practices/inline_disables/comment_ripper.rb +19 -0
  30. data/lib/rails_best_practices/inline_disables/inline_disable.rb +50 -0
  31. data/lib/rails_best_practices/lexicals/long_line_check.rb +7 -3
  32. data/lib/rails_best_practices/option_parser.rb +156 -0
  33. data/lib/rails_best_practices/prepares.rb +1 -1
  34. data/lib/rails_best_practices/prepares/controller_prepare.rb +23 -17
  35. data/lib/rails_best_practices/prepares/gemfile_prepare.rb +2 -2
  36. data/lib/rails_best_practices/prepares/helper_prepare.rb +6 -1
  37. data/lib/rails_best_practices/prepares/initializer_prepare.rb +3 -3
  38. data/lib/rails_best_practices/prepares/mailer_prepare.rb +2 -1
  39. data/lib/rails_best_practices/prepares/model_prepare.rb +63 -23
  40. data/lib/rails_best_practices/prepares/route_prepare.rb +28 -21
  41. data/lib/rails_best_practices/prepares/schema_prepare.rb +1 -1
  42. data/lib/rails_best_practices/reviews/add_model_virtual_attribute_review.rb +38 -34
  43. data/lib/rails_best_practices/reviews/always_add_db_index_review.rb +94 -88
  44. data/lib/rails_best_practices/reviews/check_destroy_return_value_review.rb +15 -5
  45. data/lib/rails_best_practices/reviews/check_save_return_value_review.rb +20 -8
  46. data/lib/rails_best_practices/reviews/default_scope_is_evil_review.rb +1 -1
  47. data/lib/rails_best_practices/reviews/dry_bundler_in_capistrano_review.rb +1 -1
  48. data/lib/rails_best_practices/reviews/hash_syntax_review.rb +16 -16
  49. data/lib/rails_best_practices/reviews/isolate_seed_data_review.rb +12 -12
  50. data/lib/rails_best_practices/reviews/keep_finders_on_their_own_model_review.rb +10 -11
  51. data/lib/rails_best_practices/reviews/law_of_demeter_review.rb +25 -24
  52. data/lib/rails_best_practices/reviews/move_code_into_controller_review.rb +4 -4
  53. data/lib/rails_best_practices/reviews/move_code_into_helper_review.rb +9 -10
  54. data/lib/rails_best_practices/reviews/move_finder_to_named_scope_review.rb +10 -11
  55. data/lib/rails_best_practices/reviews/needless_deep_nesting_review.rb +24 -22
  56. data/lib/rails_best_practices/reviews/not_rescue_exception_review.rb +1 -1
  57. data/lib/rails_best_practices/reviews/not_use_default_route_review.rb +1 -2
  58. data/lib/rails_best_practices/reviews/not_use_time_ago_in_words_review.rb +1 -1
  59. data/lib/rails_best_practices/reviews/overuse_route_customizations_review.rb +8 -8
  60. data/lib/rails_best_practices/reviews/protect_mass_assignment_review.rb +35 -32
  61. data/lib/rails_best_practices/reviews/remove_empty_helpers_review.rb +4 -4
  62. data/lib/rails_best_practices/reviews/remove_unused_methods_in_controllers_review.rb +20 -17
  63. data/lib/rails_best_practices/reviews/remove_unused_methods_in_helpers_review.rb +12 -10
  64. data/lib/rails_best_practices/reviews/remove_unused_methods_in_models_review.rb +38 -18
  65. data/lib/rails_best_practices/reviews/replace_complex_creation_with_factory_method_review.rb +11 -11
  66. data/lib/rails_best_practices/reviews/restrict_auto_generated_routes_review.rb +77 -74
  67. data/lib/rails_best_practices/reviews/review.rb +2 -1
  68. data/lib/rails_best_practices/reviews/simplify_render_in_controllers_review.rb +2 -3
  69. data/lib/rails_best_practices/reviews/simplify_render_in_views_review.rb +12 -12
  70. data/lib/rails_best_practices/reviews/use_before_filter_review.rb +14 -10
  71. data/lib/rails_best_practices/reviews/use_model_association_review.rb +15 -15
  72. data/lib/rails_best_practices/reviews/use_multipart_alternative_as_content_type_of_email_review.rb +24 -22
  73. data/lib/rails_best_practices/reviews/use_observer_review.rb +28 -28
  74. data/lib/rails_best_practices/reviews/use_parentheses_in_method_def_review.rb +6 -6
  75. data/lib/rails_best_practices/reviews/use_query_attribute_review.rb +63 -60
  76. data/lib/rails_best_practices/reviews/use_say_with_time_in_migrations_review.rb +9 -8
  77. data/lib/rails_best_practices/reviews/use_scope_access_review.rb +16 -14
  78. data/lib/rails_best_practices/reviews/use_turbo_sprockets_rails3_review.rb +2 -1
  79. data/lib/rails_best_practices/version.rb +1 -1
  80. data/rails_best_practices.gemspec +48 -49
  81. data/spec/fixtures/lib/rails_best_practices/plugins/reviews/not_use_rails_root_review.rb +1 -2
  82. data/spec/rails_best_practices/analyzer_spec.rb +73 -42
  83. data/spec/rails_best_practices/core/check_spec.rb +5 -5
  84. data/spec/rails_best_practices/core/checks_loader_spec.rb +3 -3
  85. data/spec/rails_best_practices/core/configs_spec.rb +1 -1
  86. data/spec/rails_best_practices/core/controllers_spec.rb +1 -1
  87. data/spec/rails_best_practices/core/error_spec.rb +21 -18
  88. data/spec/rails_best_practices/core/except_methods_spec.rb +7 -7
  89. data/spec/rails_best_practices/core/gems_spec.rb +4 -4
  90. data/spec/rails_best_practices/core/helpers_spec.rb +1 -1
  91. data/spec/rails_best_practices/core/klasses_spec.rb +3 -3
  92. data/spec/rails_best_practices/core/mailers_spec.rb +1 -1
  93. data/spec/rails_best_practices/core/methods_spec.rb +6 -6
  94. data/spec/rails_best_practices/core/model_associations_spec.rb +10 -6
  95. data/spec/rails_best_practices/core/model_attributes_spec.rb +4 -4
  96. data/spec/rails_best_practices/core/models_spec.rb +1 -1
  97. data/spec/rails_best_practices/core/modules_spec.rb +5 -5
  98. data/spec/rails_best_practices/core/routes_spec.rb +5 -5
  99. data/spec/rails_best_practices/core/runner_spec.rb +9 -7
  100. data/spec/rails_best_practices/core_ext/erubis_spec.rb +10 -10
  101. data/spec/rails_best_practices/inline_disables/inline_disable_spec.rb +62 -0
  102. data/spec/rails_best_practices/lexicals/long_line_check_spec.rb +32 -31
  103. data/spec/rails_best_practices/lexicals/remove_tab_check_spec.rb +6 -6
  104. data/spec/rails_best_practices/lexicals/remove_trailing_whitespace_check_spec.rb +6 -6
  105. data/spec/rails_best_practices/prepares/config_prepare_spec.rb +2 -2
  106. data/spec/rails_best_practices/prepares/controller_prepare_spec.rb +18 -10
  107. data/spec/rails_best_practices/prepares/gemfile_prepare_spec.rb +17 -17
  108. data/spec/rails_best_practices/prepares/helper_prepare_spec.rb +3 -3
  109. data/spec/rails_best_practices/prepares/initializer_prepare_spec.rb +3 -3
  110. data/spec/rails_best_practices/prepares/mailer_prepare_spec.rb +2 -2
  111. data/spec/rails_best_practices/prepares/model_prepare_spec.rb +79 -43
  112. data/spec/rails_best_practices/prepares/route_prepare_spec.rb +141 -76
  113. data/spec/rails_best_practices/prepares/schema_prepare_spec.rb +2 -2
  114. data/spec/rails_best_practices/reviews/add_model_virtual_attribute_review_spec.rb +18 -12
  115. data/spec/rails_best_practices/reviews/always_add_db_index_review_spec.rb +28 -22
  116. data/spec/rails_best_practices/reviews/check_destroy_return_value_review_spec.rb +15 -13
  117. data/spec/rails_best_practices/reviews/check_save_return_value_review_spec.rb +31 -21
  118. data/spec/rails_best_practices/reviews/default_scope_is_evil_review_spec.rb +6 -6
  119. data/spec/rails_best_practices/reviews/dry_bundler_in_capistrano_review_spec.rb +5 -5
  120. data/spec/rails_best_practices/reviews/hash_syntax_review_spec.rb +13 -13
  121. data/spec/rails_best_practices/reviews/isolate_seed_data_review_spec.rb +7 -7
  122. data/spec/rails_best_practices/reviews/keep_finders_on_their_own_model_review_spec.rb +9 -9
  123. data/spec/rails_best_practices/reviews/law_of_demeter_review_spec.rb +29 -22
  124. data/spec/rails_best_practices/reviews/move_code_into_controller_review_spec.rb +6 -6
  125. data/spec/rails_best_practices/reviews/move_code_into_helper_review_spec.rb +11 -6
  126. data/spec/rails_best_practices/reviews/move_code_into_model_review_spec.rb +32 -22
  127. data/spec/rails_best_practices/reviews/move_finder_to_named_scope_review_spec.rb +7 -7
  128. data/spec/rails_best_practices/reviews/move_model_logic_into_model_review_spec.rb +9 -7
  129. data/spec/rails_best_practices/reviews/needless_deep_nesting_review_spec.rb +9 -9
  130. data/spec/rails_best_practices/reviews/not_rescue_exception_review_spec.rb +9 -9
  131. data/spec/rails_best_practices/reviews/not_use_default_route_review_spec.rb +5 -5
  132. data/spec/rails_best_practices/reviews/not_use_time_ago_in_words_review_spec.rb +7 -7
  133. data/spec/rails_best_practices/reviews/overuse_route_customizations_review_spec.rb +7 -7
  134. data/spec/rails_best_practices/reviews/protect_mass_assignment_review_spec.rb +24 -17
  135. data/spec/rails_best_practices/reviews/remove_empty_helpers_review_spec.rb +6 -6
  136. data/spec/rails_best_practices/reviews/remove_unused_methods_in_controllers_review_spec.rb +47 -32
  137. data/spec/rails_best_practices/reviews/remove_unused_methods_in_helpers_review_spec.rb +21 -14
  138. data/spec/rails_best_practices/reviews/remove_unused_methods_in_models_review_spec.rb +57 -53
  139. data/spec/rails_best_practices/reviews/replace_complex_creation_with_factory_method_review_spec.rb +10 -8
  140. data/spec/rails_best_practices/reviews/replace_instance_variable_with_local_variable_review_spec.rb +20 -14
  141. data/spec/rails_best_practices/reviews/restrict_auto_generated_routes_review_spec.rb +54 -31
  142. data/spec/rails_best_practices/reviews/simplify_render_in_controllers_review_spec.rb +9 -9
  143. data/spec/rails_best_practices/reviews/simplify_render_in_views_review_spec.rb +13 -13
  144. data/spec/rails_best_practices/reviews/use_before_filter_review_spec.rb +11 -9
  145. data/spec/rails_best_practices/reviews/use_model_association_review_spec.rb +7 -7
  146. data/spec/rails_best_practices/reviews/use_multipart_alternative_as_content_type_of_email_review_spec.rb +35 -31
  147. data/spec/rails_best_practices/reviews/use_observer_review_spec.rb +6 -6
  148. data/spec/rails_best_practices/reviews/use_parentheses_in_method_def_review_spec.rb +10 -8
  149. data/spec/rails_best_practices/reviews/use_query_attribute_review_spec.rb +31 -24
  150. data/spec/rails_best_practices/reviews/use_say_with_time_in_migrations_review_spec.rb +15 -11
  151. data/spec/rails_best_practices/reviews/use_scope_access_review_spec.rb +14 -14
  152. data/spec/rails_best_practices/reviews/use_turbo_sprockets_rails3_review_spec.rb +61 -59
  153. metadata +21 -14
@@ -14,7 +14,17 @@ module RailsBestPractices
14
14
  # Check all "save" calls to check the return value is used by a node we have visited.
15
15
  class CheckSaveReturnValueReview < Review
16
16
  include Classable
17
- interesting_nodes :call, :command_call, :method_add_arg, :if, :ifop, :elsif, :unless, :if_mod, :unless_mod, :assign, :binary
17
+ interesting_nodes :call,
18
+ :command_call,
19
+ :method_add_arg,
20
+ :if,
21
+ :ifop,
22
+ :elsif,
23
+ :unless,
24
+ :if_mod,
25
+ :unless_mod,
26
+ :assign,
27
+ :binary
18
28
  interesting_files ALL_FILES
19
29
  url 'https://rails-bestpractices.com/posts/2012/11/02/check-the-return-value-of-save-otherwise-use-save/'
20
30
 
@@ -26,14 +36,13 @@ module RailsBestPractices
26
36
  @used_return_value_of = node.right_value
27
37
  end
28
38
 
39
+ # Consider anything used in an expression like "A or B" as used
29
40
  add_callback :start_binary do |node|
30
- # Consider anything used in an expression like "A or B" as used
31
41
  if %w[&& || and or].include?(node[2].to_s)
32
42
  all_conditions = node.all_conditions
33
43
  # if our current binary is a subset of the @used_return_value_of
34
44
  # then don't overwrite it
35
- already_included = @used_return_value_of &&
36
- (all_conditions - @used_return_value_of).empty?
45
+ already_included = @used_return_value_of && (all_conditions - @used_return_value_of).empty?
37
46
 
38
47
  @used_return_value_of = node.all_conditions unless already_included
39
48
  end
@@ -41,7 +50,8 @@ module RailsBestPractices
41
50
 
42
51
  def return_value_is_used?(node)
43
52
  return false unless @used_return_value_of
44
- node == @used_return_value_of or @used_return_value_of.include?(node)
53
+
54
+ (node == @used_return_value_of) || @used_return_value_of.include?(node)
45
55
  end
46
56
 
47
57
  def model_classnames
@@ -57,9 +67,11 @@ module RailsBestPractices
57
67
  end
58
68
  elsif message == 'create'
59
69
  # We're only interested in 'create' calls on model classes:
60
- possible_receiver_classes = [node.receiver.to_s] + classable_modules.map do |mod|
61
- "#{mod}::#{node.receiver}"
62
- end
70
+ possible_receiver_classes =
71
+ [node.receiver.to_s] +
72
+ classable_modules.map do |mod|
73
+ "#{mod}::#{node.receiver}"
74
+ end
63
75
  unless (possible_receiver_classes & model_classnames).empty?
64
76
  add_error "use 'create!' instead of 'create' as the latter may not always save"
65
77
  end
@@ -17,7 +17,7 @@ module RailsBestPractices
17
17
 
18
18
  # check all command nodes' message
19
19
  add_callback :start_command do |node|
20
- if 'default_scope' == node.message.to_s
20
+ if node.message.to_s == 'default_scope'
21
21
  add_error 'default_scope is evil'
22
22
  end
23
23
  end
@@ -20,7 +20,7 @@ module RailsBestPractices
20
20
 
21
21
  # check call node to see if it is with message "namespace" and argument "bundler".
22
22
  add_callback :start_command do |node|
23
- if 'namespace' == node.message.to_s && 'bundler' == node.arguments.all[0].to_s
23
+ if node.message.to_s == 'namespace' && node.arguments.all[0].to_s == 'bundler'
24
24
  add_error 'dry bundler in capistrano'
25
25
  end
26
26
  end
@@ -12,7 +12,7 @@ module RailsBestPractices
12
12
  interesting_nodes :hash, :bare_assoc_hash
13
13
  interesting_files ALL_FILES
14
14
 
15
- VALID_SYMBOL_KEY = /\A[@$_A-Za-z]([_\w]*[!_=?\w])?\z/
15
+ VALID_SYMBOL_KEY = /\A[@$_A-Za-z]([_\w]*[!_=?\w])?\z/.freeze
16
16
 
17
17
  # check hash node to see if it is ruby 1.8 style.
18
18
  add_callback :start_hash, :start_bare_assoc_hash do |node|
@@ -23,24 +23,24 @@ module RailsBestPractices
23
23
 
24
24
  protected
25
25
 
26
- # check if hash node is empty.
27
- def empty_hash?(node)
28
- s(:hash, nil) == node || s(:bare_assoc_hash, nil) == node
29
- end
26
+ # check if hash node is empty.
27
+ def empty_hash?(node)
28
+ s(:hash, nil) == node || s(:bare_assoc_hash, nil) == node
29
+ end
30
30
 
31
- # check if hash key/value pairs are ruby 1.8 style.
32
- def hash_is_18?(node)
33
- pair_nodes = :hash == node.sexp_type ? node[1][1] : node[1]
34
- return false if pair_nodes.blank?
31
+ # check if hash key/value pairs are ruby 1.8 style.
32
+ def hash_is_18?(node)
33
+ pair_nodes = node.sexp_type == :hash ? node[1][1] : node[1]
34
+ return false if pair_nodes.blank?
35
35
 
36
- pair_nodes.any? { |pair_node| :symbol_literal == pair_node[1].sexp_type }
37
- end
36
+ pair_nodes.any? { |pair_node| pair_node[1].sexp_type == :symbol_literal }
37
+ end
38
38
 
39
- # check if the hash keys are valid to be converted to ruby 1.9
40
- # syntax.
41
- def valid_keys?(node)
42
- node.hash_keys.all? { |key| key =~ VALID_SYMBOL_KEY }
43
- end
39
+ # check if the hash keys are valid to be converted to ruby 1.9
40
+ # syntax.
41
+ def valid_keys?(node)
42
+ node.hash_keys.all? { |key| key =~ VALID_SYMBOL_KEY }
43
+ end
44
44
  end
45
45
  end
46
46
  end
@@ -55,20 +55,20 @@ module RailsBestPractices
55
55
 
56
56
  private
57
57
 
58
- # check assignment node,
59
- # if the right vavlue is a method_add_arg node with message "new",
60
- # then remember the left value as new variable.
61
- def remember_new_variable(node)
62
- right_value = node.right_value
63
- if :method_add_arg == right_value.sexp_type && 'new' == right_value.message.to_s
64
- @new_variables << node.left_value.to_s
65
- end
58
+ # check assignment node,
59
+ # if the right vavlue is a method_add_arg node with message "new",
60
+ # then remember the left value as new variable.
61
+ def remember_new_variable(node)
62
+ right_value = node.right_value
63
+ if right_value.sexp_type == :method_add_arg && right_value.message.to_s == 'new'
64
+ @new_variables << node.left_value.to_s
66
65
  end
66
+ end
67
67
 
68
- # see if the receiver of the call node is included in the @new_varaibles.
69
- def new_record?(node)
70
- @new_variables.include? node.receiver.to_s
71
- end
68
+ # see if the receiver of the call node is included in the @new_varaibles.
69
+ def new_record?(node)
70
+ @new_variables.include? node.receiver.to_s
71
+ end
72
72
  end
73
73
  end
74
74
  end
@@ -37,17 +37,16 @@ module RailsBestPractices
37
37
 
38
38
  private
39
39
 
40
- # check if the call node is the finder of other model.
41
- #
42
- # the message of the node should be one of find, all, first or last,
43
- # and the receiver of the node should be with message :call (this is the other model),
44
- # and any of its arguments is a hash,
45
- # then it is the finder of other model.
46
- def other_finder?(node)
47
- FINDERS.include?(node[1].message.to_s) &&
48
- :call == node[1].receiver.sexp_type &&
49
- node.arguments.grep_nodes_count(sexp_type: :bare_assoc_hash) > 0
50
- end
40
+ # check if the call node is the finder of other model.
41
+ #
42
+ # the message of the node should be one of find, all, first or last,
43
+ # and the receiver of the node should be with message :call (this is the other model),
44
+ # and any of its arguments is a hash,
45
+ # then it is the finder of other model.
46
+ def other_finder?(node)
47
+ FINDERS.include?(node[1].message.to_s) && node[1].receiver.sexp_type == :call &&
48
+ node.arguments.grep_nodes_count(sexp_type: :bare_assoc_hash) > 0
49
+ end
51
50
  end
52
51
  end
53
52
  end
@@ -28,40 +28,41 @@ module RailsBestPractices
28
28
  # and the message of the receiver call node matchs one of the association name with the class name,
29
29
  # then it violates the law of demeter.
30
30
  add_callback :start_call do |node|
31
- if :call == node.receiver.sexp_type && need_delegate?(node)
31
+ if node.receiver.sexp_type == :call && need_delegate?(node)
32
32
  add_error 'law of demeter'
33
33
  end
34
34
  end
35
35
 
36
36
  private
37
37
 
38
- # check if the call node can use delegate to avoid violating law of demeter.
39
- #
40
- # if the receiver of receiver of the call node matchs any in model names,
41
- # and the message of receiver of the call node matchs any in association names,
42
- # then it needs delegate.
43
- def need_delegate?(node)
44
- return unless variable(node)
45
- class_name = variable(node).to_s.sub('@', '').classify
46
- association_name = node.receiver.message.to_s
47
- association = model_associations.get_association(class_name, association_name)
48
- attribute_name = node.message.to_s
49
- association && ASSOCIATION_METHODS.include?(association['meta']) &&
50
- is_association_attribute?(association['class_name'], association_name, attribute_name)
51
- end
38
+ # check if the call node can use delegate to avoid violating law of demeter.
39
+ #
40
+ # if the receiver of receiver of the call node matchs any in model names,
41
+ # and the message of receiver of the call node matchs any in association names,
42
+ # then it needs delegate.
43
+ def need_delegate?(node)
44
+ return unless variable(node)
52
45
 
53
- def is_association_attribute?(association_class, association_name, attribute_name)
54
- if association_name =~ /able$/
55
- models.each do |class_name|
56
- if model_associations.is_association?(class_name, association_name.sub(/able$/, '')) ||
57
- model_associations.is_association?(class_name, association_name.sub(/able$/, 's'))
58
- return true if model_attributes.is_attribute?(class_name, attribute_name)
59
- end
46
+ class_name = variable(node).to_s.sub('@', '').classify
47
+ association_name = node.receiver.message.to_s
48
+ association = model_associations.get_association(class_name, association_name)
49
+ attribute_name = node.message.to_s
50
+ association && ASSOCIATION_METHODS.include?(association['meta']) &&
51
+ is_association_attribute?(association['class_name'], association_name, attribute_name)
52
+ end
53
+
54
+ def is_association_attribute?(association_class, association_name, attribute_name)
55
+ if association_name =~ /able$/
56
+ models.each do |class_name|
57
+ if model_associations.is_association?(class_name, association_name.sub(/able$/, '')) ||
58
+ model_associations.is_association?(class_name, association_name.sub(/able$/, 's'))
59
+ return true if model_attributes.is_attribute?(class_name, attribute_name)
60
60
  end
61
- else
62
- model_attributes.is_attribute?(association_class, attribute_name)
63
61
  end
62
+ else
63
+ model_attributes.is_attribute?(association_class, attribute_name)
64
64
  end
65
+ end
65
66
  end
66
67
  end
67
68
  end
@@ -37,10 +37,10 @@ module RailsBestPractices
37
37
 
38
38
  private
39
39
 
40
- # check if the node is a finder call node.
41
- def finder?(node)
42
- node.receiver.const? && FINDERS.include?(node.message.to_s)
43
- end
40
+ # check if the node is a finder call node.
41
+ def finder?(node)
42
+ node.receiver.const? && FINDERS.include?(node.message.to_s)
43
+ end
44
44
  end
45
45
  end
46
46
  end
@@ -38,16 +38,15 @@ module RailsBestPractices
38
38
 
39
39
  private
40
40
 
41
- # check if the arguments of options_for_select are complex.
42
- #
43
- # if the first argument is an array,
44
- # and the size of array is greater than @array_count you defined,
45
- # then it is complext.
46
- def complex_select_options?(node)
47
- 'options_for_select' == node[1].message.to_s &&
48
- :array == node.arguments.all.first.sexp_type &&
49
- node.arguments.all.first.array_size > @array_count
50
- end
41
+ # check if the arguments of options_for_select are complex.
42
+ #
43
+ # if the first argument is an array,
44
+ # and the size of array is greater than @array_count you defined,
45
+ # then it is complext.
46
+ def complex_select_options?(node)
47
+ node[1].message.to_s == 'options_for_select' && node.arguments.all.first.sexp_type == :array &&
48
+ node.arguments.all.first.array_size > @array_count
49
+ end
51
50
  end
52
51
  end
53
52
  end
@@ -29,17 +29,16 @@ module RailsBestPractices
29
29
 
30
30
  private
31
31
 
32
- # check if the method_add_arg node is a finder.
33
- #
34
- # if the receiver of method_add_arg node is a constant,
35
- # and the message of call method_add_arg is one of find, all, first or last,
36
- # and any of its arguments is a hash,
37
- # then it is a finder.
38
- def finder?(node)
39
- FINDERS.include?(node[1].message.to_s) &&
40
- :call == node[1].sexp_type &&
41
- node.arguments.grep_nodes_count(sexp_type: :bare_assoc_hash) > 0
42
- end
32
+ # check if the method_add_arg node is a finder.
33
+ #
34
+ # if the receiver of method_add_arg node is a constant,
35
+ # and the message of call method_add_arg is one of find, all, first or last,
36
+ # and any of its arguments is a hash,
37
+ # then it is a finder.
38
+ def finder?(node)
39
+ FINDERS.include?(node[1].message.to_s) && node[1].sexp_type == :call &&
40
+ node.arguments.grep_nodes_count(sexp_type: :bare_assoc_hash) > 0
41
+ end
43
42
  end
44
43
  end
45
44
  end
@@ -51,30 +51,32 @@ module RailsBestPractices
51
51
 
52
52
  private
53
53
 
54
- # check nested route.
55
- #
56
- # if the receiver of the method_add_block is with message "resources" or "resource",
57
- # then increment the @counter, recursively check the block body, and decrement the @counter.
58
- #
59
- # if the node type is command_call or command,
60
- # and its message is resources or resource,
61
- # then check if @counter is greater than or equal to @nested_count,
62
- # if so, it is the needless deep nesting.
63
- def recursively_check(node)
64
- shallow = @shallow_nodes.include? node
65
- if %i[command_call command].include?(node[1].sexp_type) && %w[resources resource].include?(node[1].message.to_s)
66
- hash_node = node[1].arguments.grep_node(sexp_type: :bare_assoc_hash)
67
- shallow ||= (hash_node && 'true' == hash_node.hash_value('shallow').to_s)
68
- @counter += 1
69
- node.block_node.statements.each do |stmt_node|
70
- @shallow_nodes << stmt_node if shallow
71
- recursively_check(stmt_node)
72
- end
73
- @counter -= 1
74
- elsif %i[command_call command].include?(node.sexp_type) && %w[resources resource].include?(node.message.to_s)
75
- add_error "needless deep nesting (nested_count > #{@nested_count})", @file, node.line_number if @counter >= @nested_count && !@shallow_nodes.include?(node)
54
+ # check nested route.
55
+ #
56
+ # if the receiver of the method_add_block is with message "resources" or "resource",
57
+ # then increment the @counter, recursively check the block body, and decrement the @counter.
58
+ #
59
+ # if the node type is command_call or command,
60
+ # and its message is resources or resource,
61
+ # then check if @counter is greater than or equal to @nested_count,
62
+ # if so, it is the needless deep nesting.
63
+ def recursively_check(node)
64
+ shallow = @shallow_nodes.include? node
65
+
66
+ if %i[command_call command].include?(node[1].sexp_type) && %w[resources resource].include?(node[1].message.to_s)
67
+ hash_node = node[1].arguments.grep_node(sexp_type: :bare_assoc_hash)
68
+ shallow ||= (hash_node && hash_node.hash_value('shallow').to_s == 'true')
69
+ @counter += 1
70
+ node.block_node.statements.each do |stmt_node|
71
+ @shallow_nodes << stmt_node if shallow
72
+ recursively_check(stmt_node)
76
73
  end
74
+ @counter -= 1
75
+ elsif %i[command_call command].include?(node.sexp_type) && %w[resources resource].include?(node.message.to_s)
76
+ add_error "needless deep nesting (nested_count > #{@nested_count})", @file, node.line_number if @counter >=
77
+ @nested_count && !@shallow_nodes.include?(node)
77
78
  end
79
+ end
78
80
  end
79
81
  end
80
82
  end
@@ -18,7 +18,7 @@ module RailsBestPractices
18
18
 
19
19
  # check rescue node to see if its type is Exception
20
20
  add_callback :start_rescue do |rescue_node|
21
- if rescue_node.exception_classes.any? { |rescue_class| 'Exception' == rescue_class.to_s }
21
+ if rescue_node.exception_classes.any? { |rescue_class| rescue_class.to_s == 'Exception' }
22
22
  add_error "Don't rescue Exception", rescue_node.file, rescue_node.exception_classes.first.line_number
23
23
  end
24
24
  end
@@ -24,8 +24,7 @@ module RailsBestPractices
24
24
 
25
25
  # check all command nodes
26
26
  add_callback :start_command do |node|
27
- if 'match' == node.message.to_s &&
28
- ':controller(/:action(/:id(.:format)))' == node.arguments.all.first.to_s
27
+ if node.message.to_s == 'match' && node.arguments.all.first.to_s == ':controller(/:action(/:id(.:format)))'
29
28
  add_error 'not use default route'
30
29
  end
31
30
  end
@@ -17,7 +17,7 @@ module RailsBestPractices
17
17
 
18
18
  # check fcall node to see if its message is time_ago_in_words or distance_of_time_in_words_to_now
19
19
  add_callback :start_fcall do |node|
20
- if 'time_ago_in_words' == node.message.to_s || 'distance_of_time_in_words_to_now' == node.message.to_s
20
+ if node.message.to_s == 'time_ago_in_words' || node.message.to_s == 'distance_of_time_in_words_to_now'
21
21
  add_error 'not use time_ago_in_words'
22
22
  end
23
23
  end
@@ -41,14 +41,14 @@ module RailsBestPractices
41
41
 
42
42
  private
43
43
 
44
- # check method_add_block node to calculate the count of member and collection custom routes.
45
- #
46
- # if its receiver is with message "resources",
47
- # then calculate the count of call nodes, whose message is get, post, update or delete,
48
- # it is just the count of member and collection custom routes.
49
- def member_and_collection_count_for_rails3(node)
50
- 'resources' == node[1].message.to_s ? node.grep_nodes_count(sexp_type: :command, message: VERBS) : 0
51
- end
44
+ # check method_add_block node to calculate the count of member and collection custom routes.
45
+ #
46
+ # if its receiver is with message "resources",
47
+ # then calculate the count of call nodes, whose message is get, post, update or delete,
48
+ # it is just the count of member and collection custom routes.
49
+ def member_and_collection_count_for_rails3(node)
50
+ node[1].message.to_s == 'resources' ? node.grep_nodes_count(sexp_type: :command, message: VERBS) : 0
51
+ end
52
52
  end
53
53
  end
54
54
  end
@@ -11,6 +11,7 @@ module RailsBestPractices
11
11
  # Review process:
12
12
  # check nodes to see if there is a command with message attr_accessible or attr_protected,
13
13
  # or include ActiveModel::ForbiddenAttributesProtection.
14
+
14
15
  class ProtectMassAssignmentReview < Review
15
16
  interesting_files MODEL_FILES
16
17
  interesting_nodes :class, :command, :var_ref, :vcall, :fcall
@@ -54,53 +55,55 @@ module RailsBestPractices
54
55
 
55
56
  private
56
57
 
57
- def check_activerecord_version
58
- if Prepares.gems.gem_version('activerecord').to_i > 3
59
- @mass_assignement = false
60
- end
58
+ def check_activerecord_version
59
+ if Prepares.gems.gem_version('activerecord').to_i > 3
60
+ @mass_assignement = false
61
61
  end
62
+ end
62
63
 
63
- def check_whitelist_attributes_config
64
- if 'true' == Prepares.configs['config.active_record.whitelist_attributes']
65
- @whitelist_attributes = true
66
- end
64
+ def check_whitelist_attributes_config
65
+ if Prepares.configs['config.active_record.whitelist_attributes'] == 'true'
66
+ @whitelist_attributes = true
67
67
  end
68
+ end
68
69
 
69
- def check_include_forbidden_attributes_protection_config
70
- if 'true' == Prepares.configs['railsbp.include_forbidden_attributes_protection']
71
- @mass_assignement = false
72
- end
70
+ def check_include_forbidden_attributes_protection_config
71
+ if Prepares.configs['railsbp.include_forbidden_attributes_protection'] == 'true'
72
+ @mass_assignement = false
73
73
  end
74
+ end
74
75
 
75
- def check_rails_builtin(node)
76
- if @whitelist_attributes || [node.to_s, node.message.to_s].any? { |str| %w[attr_accessible attr_protected].include? str }
77
- @mass_assignement = false
78
- end
76
+ def check_rails_builtin(node)
77
+ if @whitelist_attributes ||
78
+ [node.to_s, node.message.to_s].any? { |str| %w[attr_accessible attr_protected].include? str }
79
+ @mass_assignement = false
79
80
  end
81
+ end
80
82
 
81
- def check_strong_parameters(command_node)
82
- if 'include' == command_node.message.to_s && 'ActiveModel::ForbiddenAttributesProtection' == command_node.arguments.all.first.to_s
83
- @mass_assignement = false
84
- end
83
+ def check_strong_parameters(command_node)
84
+ if command_node.message.to_s == 'include' &&
85
+ command_node.arguments.all.first.to_s == 'ActiveModel::ForbiddenAttributesProtection'
86
+ @mass_assignement = false
85
87
  end
88
+ end
86
89
 
87
- def check_devise(command_node)
88
- if 'devise' == command_node.message.to_s
89
- @mass_assignement = false
90
- end
90
+ def check_devise(command_node)
91
+ if command_node.message.to_s == 'devise'
92
+ @mass_assignement = false
91
93
  end
94
+ end
92
95
 
93
- def check_authlogic(node)
94
- if [node.to_s, node.message.to_s].include? 'acts_as_authentic'
95
- @mass_assignement = false
96
- end
96
+ def check_authlogic(node)
97
+ if [node.to_s, node.message.to_s].include? 'acts_as_authentic'
98
+ @mass_assignement = false
97
99
  end
100
+ end
98
101
 
99
- def check_active_record(const_path_ref_node)
100
- if 'ActiveRecord::Base' != const_path_ref_node.base_class.to_s
101
- @mass_assignement = false
102
- end
102
+ def check_active_record(const_path_ref_node)
103
+ if const_path_ref_node.base_class.to_s != 'ActiveRecord::Base'
104
+ @mass_assignement = false
103
105
  end
106
+ end
104
107
  end
105
108
  end
106
109
  end