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
@@ -13,7 +13,7 @@ module RailsBestPractices
13
13
  # then save it to as key in @variable_use_count hash, and add the call count (hash value).
14
14
  def remember_variable_use_count(node)
15
15
  variable_node = variable(node)
16
- if variable_node && 'self' != variable_node.to_s && @last_variable_node != variable_node
16
+ if variable_node && variable_node.to_s != 'self' && @last_variable_node != variable_node
17
17
  @last_variable_node = variable_node
18
18
  variable_use_count[variable_node.to_s] ||= 0
19
19
  variable_use_count[variable_node.to_s] += 1
@@ -36,6 +36,7 @@ module RailsBestPractices
36
36
  node = node.receiver
37
37
  end
38
38
  return if %i[fcall hash].include?(node.receiver.sexp_type)
39
+
39
40
  node.receiver
40
41
  end
41
42
 
@@ -21,10 +21,9 @@ module RailsBestPractices
21
21
  # if its message is render and the arguments contain a key action, template or file,
22
22
  # then it should be replaced by simplified syntax.
23
23
  add_callback :start_command do |node|
24
- if 'render' == node.message.to_s
24
+ if node.message.to_s == 'render'
25
25
  keys = node.arguments.all.first.hash_keys
26
- if keys && keys.size == 1 &&
27
- (keys.include?('action') || keys.include?('template') || keys.include?('file'))
26
+ if keys && keys.size == 1 && (keys.include?('action') || keys.include?('template') || keys.include?('file'))
28
27
  add_error 'simplify render in controllers'
29
28
  end
30
29
  end
@@ -22,10 +22,10 @@ module RailsBestPractices
22
22
  # if its message is render and the arguments contain a key partial,
23
23
  # then it should be replaced by simplified syntax.
24
24
  add_callback :start_command do |node|
25
- if 'render' == node.message.to_s
26
- hash_node = node.arguments.all.first
27
- if hash_node && :bare_assoc_hash == hash_node.sexp_type &&
28
- include_partial?(hash_node) && valid_hash?(hash_node)
25
+ if node.message.to_s == 'render'
26
+ hash_node = node.arguments.all.first
27
+ if hash_node && hash_node.sexp_type == :bare_assoc_hash && include_partial?(hash_node) &&
28
+ valid_hash?(hash_node)
29
29
  add_error 'simplify render in views'
30
30
  end
31
31
  end
@@ -33,15 +33,15 @@ module RailsBestPractices
33
33
 
34
34
  protected
35
35
 
36
- def include_partial?(hash_node)
37
- hash_node.hash_keys.include?('partial') && !hash_node.hash_value('partial').to_s.include?('/')
38
- end
36
+ def include_partial?(hash_node)
37
+ hash_node.hash_keys.include?('partial') && !hash_node.hash_value('partial').to_s.include?('/')
38
+ end
39
39
 
40
- def valid_hash?(hash_node)
41
- keys = hash_node.hash_keys
42
- keys.delete('partial')
43
- (keys - VALID_KEYS).empty?
44
- end
40
+ def valid_hash?(hash_node)
41
+ keys = hash_node.hash_keys
42
+ keys.delete('partial')
43
+ (keys - VALID_KEYS).empty?
44
+ end
45
45
  end
46
46
  end
47
47
  end
@@ -12,6 +12,7 @@ module RailsBestPractices
12
12
  # Review process:
13
13
  # check all first code line_number in method definitions (actions),
14
14
  # if they are duplicated, then they should be moved to before_filter.
15
+
15
16
  class UseBeforeFilterReview < Review
16
17
  interesting_nodes :class
17
18
  interesting_files CONTROLLER_FILES
@@ -34,10 +35,12 @@ module RailsBestPractices
34
35
  var_ref_or_vcall_included = %i[var_ref vcall].include?(statement_node.sexp_type)
35
36
  private_or_protected_included = %w[protected private].include?(statement_node.to_s)
36
37
  break if var_ref_or_vcall_included && private_or_protected_included
37
- remember_first_sentence(statement_node) if :def == statement_node.sexp_type
38
+
39
+ remember_first_sentence(statement_node) if statement_node.sexp_type == :def
38
40
  end
39
41
  @first_sentences.each do |_first_sentence, def_nodes|
40
42
  next unless def_nodes.size > @customize_count
43
+
41
44
  add_error "use before_filter for #{def_nodes.map { |node| node.method_name.to_s }.join(',')}",
42
45
  node.file,
43
46
  def_nodes.map(&:line_number).join(',')
@@ -46,16 +49,17 @@ module RailsBestPractices
46
49
 
47
50
  private
48
51
 
49
- # check method define node, and remember the first sentence.
50
- def remember_first_sentence(node)
51
- first_sentence = node.body.statements.first
52
- return unless first_sentence
53
- first_sentence = first_sentence.remove_line_and_column
54
- unless first_sentence == s(:nil)
55
- @first_sentences[first_sentence] ||= []
56
- @first_sentences[first_sentence] << node
57
- end
52
+ # check method define node, and remember the first sentence.
53
+ def remember_first_sentence(node)
54
+ first_sentence = node.body.statements.first
55
+ return unless first_sentence
56
+
57
+ first_sentence = first_sentence.remove_line_and_column
58
+ unless first_sentence == s(:nil)
59
+ @first_sentences[first_sentence] ||= []
60
+ @first_sentences[first_sentence] << node
58
61
  end
62
+ end
59
63
  end
60
64
  end
61
65
  end
@@ -43,24 +43,24 @@ module RailsBestPractices
43
43
 
44
44
  private
45
45
 
46
- # check an attribute assignment node, if its message is xxx_id,
47
- # then remember the receiver of the attribute assignment in @assignments.
48
- def attribute_assignment(node)
49
- if node.left_value.message.to_s =~ /_id$/
50
- receiver = node.left_value.receiver.to_s
51
- @assignments[receiver] = true
52
- end
46
+ # check an attribute assignment node, if its message is xxx_id,
47
+ # then remember the receiver of the attribute assignment in @assignments.
48
+ def attribute_assignment(node)
49
+ if node.left_value.message.is_a?(Sexp) && node.left_value.message.to_s =~ /_id$/
50
+ receiver = node.left_value.receiver.to_s
51
+ @assignments[receiver] = true
53
52
  end
53
+ end
54
54
 
55
- # check a call node with message "save" or "save!",
56
- # if the receiver of call node exists in @assignments,
57
- # then the attribute assignment should be replaced by using model association.
58
- def call_assignment(node)
59
- if ['save', 'save!'].include? node.message.to_s
60
- receiver = node.receiver.to_s
61
- add_error "use model association (for #{receiver})" if @assignments[receiver]
62
- end
55
+ # check a call node with message "save" or "save!",
56
+ # if the receiver of call node exists in @assignments,
57
+ # then the attribute assignment should be replaced by using model association.
58
+ def call_assignment(node)
59
+ if ['save', 'save!'].include? node.message.to_s
60
+ receiver = node.receiver.to_s
61
+ add_error "use model association (for #{receiver})" if @assignments[receiver]
63
62
  end
63
+ end
64
64
  end
65
65
  end
66
66
  end
@@ -11,6 +11,7 @@ module RailsBestPractices
11
11
  # Review process:
12
12
  # check class node to remember the class name,
13
13
  # and check the method definition nodes to see if the corresponding mailer views exist or not.
14
+
14
15
  class UseMultipartAlternativeAsContentTypeOfEmailReview < Review
15
16
  interesting_nodes :class, :def
16
17
  interesting_files MAILER_FILES
@@ -31,30 +32,31 @@ module RailsBestPractices
31
32
 
32
33
  private
33
34
 
34
- # check if rails's syntax mailer views are canonical.
35
- #
36
- # @param [String] name method name in action_mailer
37
- def rails_canonical_mailer_views?(name); end
38
-
39
- # check if rails3's syntax mailer views are canonical.
40
- #
41
- # @param [String] name method name in action_mailer
42
- def rails3_canonical_mailer_views?(name)
43
- return true if mailer_files(name).empty?
44
- return true if mailer_files(name).none? { |filename| filename.index 'html' }
45
- mailer_files(name).any? { |filename| filename.index 'html' } &&
46
- mailer_files(name).any? { |filename| filename.index 'text' }
47
- end
35
+ # check if rails's syntax mailer views are canonical.
36
+ #
37
+ # @param [String] name method name in action_mailer
38
+ def rails_canonical_mailer_views?(name); end
48
39
 
49
- # all mail view files for a method name.
50
- def mailer_files(name)
51
- Dir.entries(mailer_directory) { |filename| filename.index name.to_s }
52
- end
40
+ # check if rails3's syntax mailer views are canonical.
41
+ #
42
+ # @param [String] name method name in action_mailer
43
+ def rails3_canonical_mailer_views?(name)
44
+ return true if mailer_files(name).empty?
45
+ return true if mailer_files(name).none? { |filename| filename.index 'html' }
53
46
 
54
- # the view directory of mailer.
55
- def mailer_directory
56
- File.join(Core::Runner.base_path, "app/views/#{@klazz_name.to_s.underscore}")
57
- end
47
+ mailer_files(name).any? { |filename| filename.index 'html' } &&
48
+ mailer_files(name).any? { |filename| filename.index 'text' }
49
+ end
50
+
51
+ # all mail view files for a method name.
52
+ def mailer_files(name)
53
+ Dir.entries(mailer_directory) { |filename| filename.index name.to_s }
54
+ end
55
+
56
+ # the view directory of mailer.
57
+ def mailer_directory
58
+ File.join(Core::Runner.base_path, "app/views/#{@klazz_name.to_s.underscore}")
59
+ end
58
60
  end
59
61
  end
60
62
  end
@@ -49,42 +49,42 @@ module RailsBestPractices
49
49
 
50
50
  private
51
51
 
52
- # check a command node, if it is a callback definition, such as after_create, before_create,
53
- # then save the callback methods in @callbacks
54
- def remember_callback(node)
55
- if node.message.to_s =~ /^after_|^before_/
56
- node.arguments.all.each do |argument|
57
- # ignore callback like after_create Comment.new
58
- @callbacks << argument.to_s if :symbol_literal == argument.sexp_type
59
- end
52
+ # check a command node, if it is a callback definition, such as after_create, before_create,
53
+ # then save the callback methods in @callbacks
54
+ def remember_callback(node)
55
+ if node.message.to_s =~ /^after_|^before_/
56
+ node.arguments.all.each do |argument|
57
+ # ignore callback like after_create Comment.new
58
+ @callbacks << argument.to_s if argument.sexp_type == :symbol_literal
60
59
  end
61
60
  end
61
+ end
62
62
 
63
- # check a defn node to see if the method name exists in the @callbacks.
64
- def callback_method?(node)
65
- @callbacks.find { |callback| callback == node.method_name.to_s }
66
- end
63
+ # check a defn node to see if the method name exists in the @callbacks.
64
+ def callback_method?(node)
65
+ @callbacks.find { |callback| callback == node.method_name.to_s }
66
+ end
67
67
 
68
- # check a def node to see if it contains a actionmailer deliver call.
69
- #
70
- # if the message of call node is deliver,
71
- # and the receiver of the call node is with receiver node who exists in @callbacks,
72
- # then the call node is actionmailer deliver call.
73
- def deliver_mailer?(node)
74
- node.grep_nodes(sexp_type: :call) do |child_node|
75
- if 'deliver' == child_node.message.to_s
76
- if :method_add_arg == child_node.receiver.sexp_type &&
77
- mailers.include?(child_node.receiver[1].receiver.to_s)
78
- return true
79
- end
68
+ # check a def node to see if it contains a actionmailer deliver call.
69
+ #
70
+ # if the message of call node is deliver,
71
+ # and the receiver of the call node is with receiver node who exists in @callbacks,
72
+ # then the call node is actionmailer deliver call.
73
+ def deliver_mailer?(node)
74
+ node.grep_nodes(sexp_type: :call) do |child_node|
75
+ if child_node.message.to_s == 'deliver'
76
+ if child_node.receiver.sexp_type == :method_add_arg &&
77
+ mailers.include?(child_node.receiver[1].receiver.to_s)
78
+ return true
80
79
  end
81
80
  end
82
- false
83
81
  end
82
+ false
83
+ end
84
84
 
85
- def mailers
86
- @mailers ||= Prepares.mailers
87
- end
85
+ def mailers
86
+ @mailers ||= Prepares.mailers
87
+ end
88
88
  end
89
89
  end
90
90
  end
@@ -21,13 +21,13 @@ module RailsBestPractices
21
21
 
22
22
  protected
23
23
 
24
- def no_parentheses_around_parameters?(def_node)
25
- :parent != def_node[2][0]
26
- end
24
+ def no_parentheses_around_parameters?(def_node)
25
+ def_node[2][0] != :parent
26
+ end
27
27
 
28
- def has_parameters?(def_node)
29
- :params == def_node[2][0] && !def_node[2][1..-1].compact.empty?
30
- end
28
+ def has_parameters?(def_node)
29
+ def_node[2][0] == :params && !def_node[2][1..-1].compact.empty?
30
+ end
31
31
  end
32
32
  end
33
33
  end
@@ -34,13 +34,15 @@ module RailsBestPractices
34
34
  #
35
35
  # then the call node can use query attribute instead.
36
36
  add_callback :start_if, :start_unless, :start_elsif, :start_ifop, :start_if_mod, :start_unless_mod do |node|
37
- all_conditions = if node.conditional_statement == node.conditional_statement.all_conditions
38
- [node.conditional_statement]
39
- else
40
- node.conditional_statement.all_conditions
41
- end
37
+ all_conditions =
38
+ if node.conditional_statement == node.conditional_statement.all_conditions
39
+ [node.conditional_statement]
40
+ else
41
+ node.conditional_statement.all_conditions
42
+ end
42
43
  all_conditions.each do |condition_node|
43
44
  next unless query_attribute_node = query_attribute_node(condition_node)
45
+
44
46
  receiver_node = query_attribute_node.receiver
45
47
  add_error "use query attribute (#{receiver_node.receiver}.#{receiver_node.message}?)",
46
48
  node.file,
@@ -50,67 +52,68 @@ module RailsBestPractices
50
52
 
51
53
  private
52
54
 
53
- # recursively check conditional statement nodes to see if there is a call node that may be
54
- # possible query attribute.
55
- def query_attribute_node(conditional_statement_node)
56
- case conditional_statement_node.sexp_type
57
- when :and, :or
58
- node = query_attribute_node(conditional_statement_node[1]) ||
59
- query_attribute_node(conditional_statement_node[2])
60
- node.file = conditional_statement_code.file
61
- return node
62
- when :not
63
- node = query_attribute_node(conditional_statement_node[1])
64
- node.file = conditional_statement_node.file
65
- when :call
66
- return conditional_statement_node if possible_query_attribute?(conditional_statement_node)
67
- when :binary
68
- return conditional_statement_node if possible_query_attribute?(conditional_statement_node)
69
- end
70
- nil
55
+ # recursively check conditional statement nodes to see if there is a call node that may be
56
+ # possible query attribute.
57
+ def query_attribute_node(conditional_statement_node)
58
+ case conditional_statement_node.sexp_type
59
+ when :and, :or
60
+ node =
61
+ query_attribute_node(conditional_statement_node[1]) || query_attribute_node(conditional_statement_node[2])
62
+ node.file = conditional_statement_code.file
63
+ return node
64
+ when :not
65
+ node = query_attribute_node(conditional_statement_node[1])
66
+ node.file = conditional_statement_node.file
67
+ when :call
68
+ return conditional_statement_node if possible_query_attribute?(conditional_statement_node)
69
+ when :binary
70
+ return conditional_statement_node if possible_query_attribute?(conditional_statement_node)
71
71
  end
72
+ nil
73
+ end
72
74
 
73
- # check if the node may use query attribute instead.
74
- #
75
- # if the node contains two method calls, e.g. @user.login.nil?
76
- #
77
- # for the first call, the receiver should be one of the class names and
78
- # the message should be one of the attribute name.
79
- #
80
- # for the second call, the message should be one of nil?, blank? or present? or
81
- # it is compared with an empty string.
82
- #
83
- # the node that may use query attribute.
84
- def possible_query_attribute?(node)
85
- return false unless :call == node.receiver.sexp_type
86
- variable_node = variable(node)
87
- message_node = node.grep_node(receiver: variable_node.to_s).message
75
+ # check if the node may use query attribute instead.
76
+ #
77
+ # if the node contains two method calls, e.g. @user.login.nil?
78
+ #
79
+ # for the first call, the receiver should be one of the class names and
80
+ # the message should be one of the attribute name.
81
+ #
82
+ # for the second call, the message should be one of nil?, blank? or present? or
83
+ # it is compared with an empty string.
84
+ #
85
+ # the node that may use query attribute.
86
+ def possible_query_attribute?(node)
87
+ return false unless node.receiver.sexp_type == :call
88
88
 
89
- is_model?(variable_node) && model_attribute?(variable_node, message_node.to_s) &&
90
- (QUERY_METHODS.include?(node.message.to_s) || compare_with_empty_string?(node))
91
- end
89
+ variable_node = variable(node)
90
+ message_node = node.grep_node(receiver: variable_node.to_s).message
92
91
 
93
- # check if the receiver is one of the models.
94
- def is_model?(variable_node)
95
- return false if variable_node.const?
96
- class_name = variable_node.to_s.sub(/^@/, '').classify
97
- models.include?(class_name)
98
- end
92
+ is_model?(variable_node) && model_attribute?(variable_node, message_node.to_s) &&
93
+ (QUERY_METHODS.include?(node.message.to_s) || compare_with_empty_string?(node))
94
+ end
99
95
 
100
- # check if the receiver and message is one of the model's attribute.
101
- # the receiver should match one of the class model name, and the message should match one of attribute name.
102
- def model_attribute?(variable_node, message)
103
- class_name = variable_node.to_s.sub(/^@/, '').classify
104
- attribute_type = model_attributes.get_attribute_type(class_name, message)
105
- attribute_type && !%w[integer float].include?(attribute_type)
106
- end
96
+ # check if the receiver is one of the models.
97
+ def is_model?(variable_node)
98
+ return false if variable_node.const?
107
99
 
108
- # check if the node is with node type :binary, node message :== and node argument is empty string.
109
- def compare_with_empty_string?(node)
110
- :binary == node.sexp_type &&
111
- ['==', '!='].include?(node.message.to_s) &&
112
- s(:string_literal, s(:string_content)) == node.argument
113
- end
100
+ class_name = variable_node.to_s.sub(/^@/, '').classify
101
+ models.include?(class_name)
102
+ end
103
+
104
+ # check if the receiver and message is one of the model's attribute.
105
+ # the receiver should match one of the class model name, and the message should match one of attribute name.
106
+ def model_attribute?(variable_node, message)
107
+ class_name = variable_node.to_s.sub(/^@/, '').classify
108
+ attribute_type = model_attributes.get_attribute_type(class_name, message)
109
+ attribute_type && !%w[integer float].include?(attribute_type)
110
+ end
111
+
112
+ # check if the node is with node type :binary, node message :== and node argument is empty string.
113
+ def compare_with_empty_string?(node)
114
+ node.sexp_type == :binary && ['==', '!='].include?(node.message.to_s) &&
115
+ s(:string_literal, s(:string_content)) == node.argument
116
+ end
114
117
  end
115
118
  end
116
119
  end