rails_best_practices 1.19.2 → 1.20.1

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 (149) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +0 -1
  3. data/.travis.yml +2 -3
  4. data/CHANGELOG.md +7 -7
  5. data/Gemfile +3 -5
  6. data/Gemfile.lock +125 -0
  7. data/Guardfile +2 -0
  8. data/README.md +6 -6
  9. data/Rakefile +2 -17
  10. data/assets/result.html.erb +2 -0
  11. data/lib/rails_best_practices.rb +3 -2
  12. data/lib/rails_best_practices/analyzer.rb +61 -49
  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 +64 -56
  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 +67 -73
  28. data/lib/rails_best_practices/lexicals/long_line_check.rb +7 -3
  29. data/lib/rails_best_practices/option_parser.rb +156 -0
  30. data/lib/rails_best_practices/prepares.rb +1 -1
  31. data/lib/rails_best_practices/prepares/controller_prepare.rb +24 -17
  32. data/lib/rails_best_practices/prepares/gemfile_prepare.rb +2 -2
  33. data/lib/rails_best_practices/prepares/helper_prepare.rb +6 -1
  34. data/lib/rails_best_practices/prepares/initializer_prepare.rb +3 -3
  35. data/lib/rails_best_practices/prepares/mailer_prepare.rb +2 -1
  36. data/lib/rails_best_practices/prepares/model_prepare.rb +63 -23
  37. data/lib/rails_best_practices/prepares/route_prepare.rb +28 -21
  38. data/lib/rails_best_practices/prepares/schema_prepare.rb +1 -1
  39. data/lib/rails_best_practices/reviews/add_model_virtual_attribute_review.rb +38 -34
  40. data/lib/rails_best_practices/reviews/always_add_db_index_review.rb +94 -89
  41. data/lib/rails_best_practices/reviews/check_destroy_return_value_review.rb +15 -5
  42. data/lib/rails_best_practices/reviews/check_save_return_value_review.rb +20 -8
  43. data/lib/rails_best_practices/reviews/default_scope_is_evil_review.rb +1 -1
  44. data/lib/rails_best_practices/reviews/dry_bundler_in_capistrano_review.rb +1 -1
  45. data/lib/rails_best_practices/reviews/hash_syntax_review.rb +16 -16
  46. data/lib/rails_best_practices/reviews/isolate_seed_data_review.rb +12 -12
  47. data/lib/rails_best_practices/reviews/keep_finders_on_their_own_model_review.rb +10 -11
  48. data/lib/rails_best_practices/reviews/law_of_demeter_review.rb +25 -24
  49. data/lib/rails_best_practices/reviews/move_code_into_controller_review.rb +4 -4
  50. data/lib/rails_best_practices/reviews/move_code_into_helper_review.rb +9 -10
  51. data/lib/rails_best_practices/reviews/move_finder_to_named_scope_review.rb +10 -11
  52. data/lib/rails_best_practices/reviews/needless_deep_nesting_review.rb +24 -22
  53. data/lib/rails_best_practices/reviews/not_rescue_exception_review.rb +1 -1
  54. data/lib/rails_best_practices/reviews/not_use_default_route_review.rb +1 -2
  55. data/lib/rails_best_practices/reviews/not_use_time_ago_in_words_review.rb +1 -1
  56. data/lib/rails_best_practices/reviews/overuse_route_customizations_review.rb +8 -8
  57. data/lib/rails_best_practices/reviews/protect_mass_assignment_review.rb +35 -32
  58. data/lib/rails_best_practices/reviews/remove_empty_helpers_review.rb +4 -4
  59. data/lib/rails_best_practices/reviews/remove_unused_methods_in_controllers_review.rb +26 -19
  60. data/lib/rails_best_practices/reviews/remove_unused_methods_in_helpers_review.rb +12 -10
  61. data/lib/rails_best_practices/reviews/remove_unused_methods_in_models_review.rb +38 -18
  62. data/lib/rails_best_practices/reviews/replace_complex_creation_with_factory_method_review.rb +11 -11
  63. data/lib/rails_best_practices/reviews/restrict_auto_generated_routes_review.rb +77 -74
  64. data/lib/rails_best_practices/reviews/review.rb +2 -1
  65. data/lib/rails_best_practices/reviews/simplify_render_in_controllers_review.rb +2 -3
  66. data/lib/rails_best_practices/reviews/simplify_render_in_views_review.rb +12 -12
  67. data/lib/rails_best_practices/reviews/use_before_filter_review.rb +18 -15
  68. data/lib/rails_best_practices/reviews/use_model_association_review.rb +15 -15
  69. data/lib/rails_best_practices/reviews/use_multipart_alternative_as_content_type_of_email_review.rb +24 -22
  70. data/lib/rails_best_practices/reviews/use_observer_review.rb +28 -28
  71. data/lib/rails_best_practices/reviews/use_parentheses_in_method_def_review.rb +6 -6
  72. data/lib/rails_best_practices/reviews/use_query_attribute_review.rb +68 -66
  73. data/lib/rails_best_practices/reviews/use_say_with_time_in_migrations_review.rb +9 -8
  74. data/lib/rails_best_practices/reviews/use_scope_access_review.rb +16 -14
  75. data/lib/rails_best_practices/reviews/use_turbo_sprockets_rails3_review.rb +2 -1
  76. data/lib/rails_best_practices/version.rb +1 -1
  77. data/rails_best_practices.gemspec +38 -43
  78. data/spec/fixtures/lib/rails_best_practices/plugins/reviews/not_use_rails_root_review.rb +1 -2
  79. data/spec/rails_best_practices/analyzer_spec.rb +73 -42
  80. data/spec/rails_best_practices/core/check_spec.rb +5 -5
  81. data/spec/rails_best_practices/core/checks_loader_spec.rb +3 -3
  82. data/spec/rails_best_practices/core/configs_spec.rb +1 -1
  83. data/spec/rails_best_practices/core/controllers_spec.rb +1 -1
  84. data/spec/rails_best_practices/core/error_spec.rb +21 -18
  85. data/spec/rails_best_practices/core/except_methods_spec.rb +7 -7
  86. data/spec/rails_best_practices/core/gems_spec.rb +4 -4
  87. data/spec/rails_best_practices/core/helpers_spec.rb +1 -1
  88. data/spec/rails_best_practices/core/klasses_spec.rb +3 -3
  89. data/spec/rails_best_practices/core/mailers_spec.rb +1 -1
  90. data/spec/rails_best_practices/core/methods_spec.rb +6 -6
  91. data/spec/rails_best_practices/core/model_associations_spec.rb +10 -6
  92. data/spec/rails_best_practices/core/model_attributes_spec.rb +4 -4
  93. data/spec/rails_best_practices/core/models_spec.rb +1 -1
  94. data/spec/rails_best_practices/core/modules_spec.rb +5 -5
  95. data/spec/rails_best_practices/core/routes_spec.rb +5 -5
  96. data/spec/rails_best_practices/core/runner_spec.rb +9 -7
  97. data/spec/rails_best_practices/core_ext/erubis_spec.rb +10 -10
  98. data/spec/rails_best_practices/lexicals/long_line_check_spec.rb +32 -31
  99. data/spec/rails_best_practices/lexicals/remove_tab_check_spec.rb +6 -6
  100. data/spec/rails_best_practices/lexicals/remove_trailing_whitespace_check_spec.rb +6 -6
  101. data/spec/rails_best_practices/prepares/config_prepare_spec.rb +2 -2
  102. data/spec/rails_best_practices/prepares/controller_prepare_spec.rb +18 -10
  103. data/spec/rails_best_practices/prepares/gemfile_prepare_spec.rb +17 -17
  104. data/spec/rails_best_practices/prepares/helper_prepare_spec.rb +3 -3
  105. data/spec/rails_best_practices/prepares/initializer_prepare_spec.rb +3 -3
  106. data/spec/rails_best_practices/prepares/mailer_prepare_spec.rb +2 -2
  107. data/spec/rails_best_practices/prepares/model_prepare_spec.rb +79 -43
  108. data/spec/rails_best_practices/prepares/route_prepare_spec.rb +141 -76
  109. data/spec/rails_best_practices/prepares/schema_prepare_spec.rb +2 -2
  110. data/spec/rails_best_practices/reviews/add_model_virtual_attribute_review_spec.rb +18 -12
  111. data/spec/rails_best_practices/reviews/always_add_db_index_review_spec.rb +28 -22
  112. data/spec/rails_best_practices/reviews/check_destroy_return_value_review_spec.rb +15 -13
  113. data/spec/rails_best_practices/reviews/check_save_return_value_review_spec.rb +31 -21
  114. data/spec/rails_best_practices/reviews/default_scope_is_evil_review_spec.rb +6 -6
  115. data/spec/rails_best_practices/reviews/dry_bundler_in_capistrano_review_spec.rb +5 -5
  116. data/spec/rails_best_practices/reviews/hash_syntax_review_spec.rb +13 -13
  117. data/spec/rails_best_practices/reviews/isolate_seed_data_review_spec.rb +7 -7
  118. data/spec/rails_best_practices/reviews/keep_finders_on_their_own_model_review_spec.rb +9 -9
  119. data/spec/rails_best_practices/reviews/law_of_demeter_review_spec.rb +29 -22
  120. data/spec/rails_best_practices/reviews/move_code_into_controller_review_spec.rb +6 -6
  121. data/spec/rails_best_practices/reviews/move_code_into_helper_review_spec.rb +11 -6
  122. data/spec/rails_best_practices/reviews/move_code_into_model_review_spec.rb +32 -22
  123. data/spec/rails_best_practices/reviews/move_finder_to_named_scope_review_spec.rb +7 -7
  124. data/spec/rails_best_practices/reviews/move_model_logic_into_model_review_spec.rb +9 -7
  125. data/spec/rails_best_practices/reviews/needless_deep_nesting_review_spec.rb +9 -9
  126. data/spec/rails_best_practices/reviews/not_rescue_exception_review_spec.rb +9 -9
  127. data/spec/rails_best_practices/reviews/not_use_default_route_review_spec.rb +5 -5
  128. data/spec/rails_best_practices/reviews/not_use_time_ago_in_words_review_spec.rb +7 -7
  129. data/spec/rails_best_practices/reviews/overuse_route_customizations_review_spec.rb +7 -7
  130. data/spec/rails_best_practices/reviews/protect_mass_assignment_review_spec.rb +24 -17
  131. data/spec/rails_best_practices/reviews/remove_empty_helpers_review_spec.rb +6 -6
  132. data/spec/rails_best_practices/reviews/remove_unused_methods_in_controllers_review_spec.rb +64 -31
  133. data/spec/rails_best_practices/reviews/remove_unused_methods_in_helpers_review_spec.rb +21 -14
  134. data/spec/rails_best_practices/reviews/remove_unused_methods_in_models_review_spec.rb +57 -53
  135. data/spec/rails_best_practices/reviews/replace_complex_creation_with_factory_method_review_spec.rb +10 -8
  136. data/spec/rails_best_practices/reviews/replace_instance_variable_with_local_variable_review_spec.rb +20 -14
  137. data/spec/rails_best_practices/reviews/restrict_auto_generated_routes_review_spec.rb +54 -31
  138. data/spec/rails_best_practices/reviews/simplify_render_in_controllers_review_spec.rb +9 -9
  139. data/spec/rails_best_practices/reviews/simplify_render_in_views_review_spec.rb +13 -13
  140. data/spec/rails_best_practices/reviews/use_before_filter_review_spec.rb +11 -9
  141. data/spec/rails_best_practices/reviews/use_model_association_review_spec.rb +7 -7
  142. data/spec/rails_best_practices/reviews/use_multipart_alternative_as_content_type_of_email_review_spec.rb +35 -31
  143. data/spec/rails_best_practices/reviews/use_observer_review_spec.rb +6 -6
  144. data/spec/rails_best_practices/reviews/use_parentheses_in_method_def_review_spec.rb +10 -8
  145. data/spec/rails_best_practices/reviews/use_query_attribute_review_spec.rb +31 -24
  146. data/spec/rails_best_practices/reviews/use_say_with_time_in_migrations_review_spec.rb +15 -11
  147. data/spec/rails_best_practices/reviews/use_scope_access_review_spec.rb +14 -14
  148. data/spec/rails_best_practices/reviews/use_turbo_sprockets_rails3_review_spec.rb +61 -59
  149. metadata +16 -18
@@ -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,84 +34,86 @@ 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
42
- all_conditions.each do |condition_node|
43
- if query_attribute_node = query_attribute_node(condition_node)
44
- receiver_node = query_attribute_node.receiver
45
- add_error "use query attribute (#{receiver_node.receiver}.#{receiver_node.message}?)",
46
- node.file,
47
- query_attribute_node.line_number
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
48
42
  end
43
+ all_conditions.each do |condition_node|
44
+ next unless query_attribute_node = query_attribute_node(condition_node)
45
+
46
+ receiver_node = query_attribute_node.receiver
47
+ add_error "use query attribute (#{receiver_node.receiver}.#{receiver_node.message}?)",
48
+ node.file,
49
+ query_attribute_node.line_number
49
50
  end
50
51
  end
51
52
 
52
53
  private
53
54
 
54
- # recursively check conditional statement nodes to see if there is a call node that may be
55
- # possible query attribute.
56
- def query_attribute_node(conditional_statement_node)
57
- case conditional_statement_node.sexp_type
58
- when :and, :or
59
- node = query_attribute_node(conditional_statement_node[1]) ||
60
- query_attribute_node(conditional_statement_node[2])
61
- node.file = conditional_statement_code.file
62
- return node
63
- when :not
64
- node = query_attribute_node(conditional_statement_node[1])
65
- node.file = conditional_statement_node.file
66
- when :call
67
- return conditional_statement_node if possible_query_attribute?(conditional_statement_node)
68
- when :binary
69
- return conditional_statement_node if possible_query_attribute?(conditional_statement_node)
70
- end
71
- 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)
72
71
  end
72
+ nil
73
+ end
74
+
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
73
88
 
74
- # check if the node may use query attribute instead.
75
- #
76
- # if the node contains two method calls, e.g. @user.login.nil?
77
- #
78
- # for the first call, the receiver should be one of the class names and
79
- # the message should be one of the attribute name.
80
- #
81
- # for the second call, the message should be one of nil?, blank? or present? or
82
- # it is compared with an empty string.
83
- #
84
- # the node that may use query attribute.
85
- def possible_query_attribute?(node)
86
- return false unless :call == node.receiver.sexp_type
87
- variable_node = variable(node)
88
- message_node = node.grep_node(receiver: variable_node.to_s).message
89
+ variable_node = variable(node)
90
+ message_node = node.grep_node(receiver: variable_node.to_s).message
89
91
 
90
- is_model?(variable_node) && model_attribute?(variable_node, message_node.to_s) &&
91
- (QUERY_METHODS.include?(node.message.to_s) || compare_with_empty_string?(node))
92
- 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
93
95
 
94
- # check if the receiver is one of the models.
95
- def is_model?(variable_node)
96
- return false if variable_node.const?
97
- class_name = variable_node.to_s.sub(/^@/, '').classify
98
- models.include?(class_name)
99
- end
96
+ # check if the receiver is one of the models.
97
+ def is_model?(variable_node)
98
+ return false if variable_node.const?
100
99
 
101
- # check if the receiver and message is one of the model's attribute.
102
- # the receiver should match one of the class model name, and the message should match one of attribute name.
103
- def model_attribute?(variable_node, message)
104
- class_name = variable_node.to_s.sub(/^@/, '').classify
105
- attribute_type = model_attributes.get_attribute_type(class_name, message)
106
- attribute_type && !%w[integer float].include?(attribute_type)
107
- end
100
+ class_name = variable_node.to_s.sub(/^@/, '').classify
101
+ models.include?(class_name)
102
+ end
108
103
 
109
- # check if the node is with node type :binary, node message :== and node argument is empty string.
110
- def compare_with_empty_string?(node)
111
- :binary == node.sexp_type &&
112
- ['==', '!='].include?(node.message.to_s) &&
113
- s(:string_literal, s(:string_content)) == node.argument
114
- end
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
115
117
  end
116
118
  end
117
119
  end
@@ -31,14 +31,15 @@ module RailsBestPractices
31
31
  node.body.statements.each do |child_node|
32
32
  next if child_node.grep_nodes_count(sexp_type: %i[fcall command], message: WITH_SAY_METHODS) > 0
33
33
 
34
- receiver_node = if :method_add_block == child_node.sexp_type
35
- child_node[1]
36
- elsif :method_add_arg == child_node.sexp_type
37
- child_node[1]
38
- else
39
- child_node
40
- end
41
- if :call == receiver_node.sexp_type
34
+ receiver_node =
35
+ if child_node.sexp_type == :method_add_block
36
+ child_node[1]
37
+ elsif child_node.sexp_type == :method_add_arg
38
+ child_node[1]
39
+ else
40
+ child_node
41
+ end
42
+ if receiver_node.sexp_type == :call
42
43
  add_error('use say with time in migrations', node.file, child_node.line_number)
43
44
  end
44
45
  end
@@ -30,28 +30,30 @@ module RailsBestPractices
30
30
 
31
31
  private
32
32
 
33
- # check a if node to see
34
- #
35
- # if the conditional statement is compared with current_user or current_user.id,
36
- # and there is a redirect_to method call in the block body,
37
- # then it should be replaced by using scope access.
38
- def current_user_redirect?(node)
39
- all_conditions = if node.conditional_statement == node.conditional_statement.all_conditions
33
+ # check a if node to see
34
+ #
35
+ # if the conditional statement is compared with current_user or current_user.id,
36
+ # and there is a redirect_to method call in the block body,
37
+ # then it should be replaced by using scope access.
38
+ def current_user_redirect?(node)
39
+ all_conditions =
40
+ if node.conditional_statement == node.conditional_statement.all_conditions
40
41
  [node.conditional_statement]
41
42
  else
42
43
  node.conditional_statement.all_conditions
43
44
  end
44
- results = all_conditions.map do |condition_node|
45
+ results =
46
+ all_conditions.map do |condition_node|
45
47
  ['==', '!='].include?(condition_node.message.to_s) &&
46
48
  (current_user?(condition_node.argument) || current_user?(condition_node.receiver))
47
49
  end
48
- results.any? { |result| result == true } && node.body.grep_node(message: 'redirect_to')
49
- end
50
+ results.any? { |result| result == true } && node.body.grep_node(message: 'redirect_to')
51
+ end
50
52
 
51
- # check a call node to see if it uses current_user, or current_user.id.
52
- def current_user?(node)
53
- 'current_user' == node.to_s || ('current_user' == node.receiver.to_s && 'id' == node.message.to_s)
54
- end
53
+ # check a call node to see if it uses current_user, or current_user.id.
54
+ def current_user?(node)
55
+ node.to_s == 'current_user' || (node.receiver.to_s == 'current_user' && node.message.to_s == 'id')
56
+ end
55
57
  end
56
58
  end
57
59
  end
@@ -18,7 +18,8 @@ module RailsBestPractices
18
18
  # check command node to see if load 'deploy/assets'
19
19
  add_callback :start_command do |node|
20
20
  if Prepares.gems.gem_version('rails').to_i == 3
21
- if !Prepares.gems.has_gem?('turbo-sprockets-rails3') && 'load' == node.message.to_s && 'deploy/assets' == node.arguments.to_s
21
+ if !Prepares.gems.has_gem?('turbo-sprockets-rails3') && node.message.to_s == 'load' &&
22
+ node.arguments.to_s == 'deploy/assets'
22
23
  add_error 'speed up assets precompile with turbo-sprockets-rails3'
23
24
  end
24
25
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsBestPractices
4
- VERSION = '1.19.2'.freeze
4
+ VERSION = '1.20.1'
5
5
  end
@@ -1,59 +1,54 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require File.expand_path('../lib/rails_best_practices/version', __FILE__)
3
+ require File.expand_path('lib/rails_best_practices/version', __dir__)
4
4
 
5
- Gem::Specification.new do |s|
6
- s.name = 'rails_best_practices'
7
- s.version = RailsBestPractices::VERSION
8
- s.platform = Gem::Platform::RUBY
9
- s.authors = ['Richard Huang']
10
- s.email = ['flyerhzm@gmail.com']
11
- s.homepage = 'http://rails-bestpractices.com'
12
- s.summary = 'a code metric tool for rails codes.'
13
- s.description = 'a code metric tool for rails codes, written in Ruby.'
14
- s.license = 'MIT'
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'rails_best_practices'
7
+ spec.version = RailsBestPractices::VERSION
8
+ spec.platform = Gem::Platform::RUBY
9
+ spec.authors = ['Richard Huang']
10
+ spec.email = ['flyerhzm@gmail.com']
11
+ spec.homepage = 'http://rails-bestpractices.com'
12
+ spec.summary = 'a code metric tool for rails codes.'
13
+ spec.description = 'a code metric tool for rails codes, written in Ruby.'
14
+ spec.license = 'MIT'
15
15
 
16
- s.required_ruby_version = '>= 1.9.0'
17
- s.required_rubygems_version = '>= 1.3.6'
16
+ spec.required_ruby_version = '>= 1.9.0'
17
+ spec.required_rubygems_version = '>= 1.3.6'
18
18
 
19
- s.add_dependency('activesupport')
20
- # TODO: add a dependency for Rails >= 3 ?
21
- s.add_dependency('code_analyzer', '>= 0.4.8')
22
- s.add_dependency('erubis')
23
- s.add_dependency('i18n')
24
- s.add_dependency('json')
25
- s.add_dependency('require_all', '~> 2.0')
26
- s.add_dependency('ruby-progressbar')
19
+ spec.add_dependency('activesupport')
20
+ spec.add_dependency('code_analyzer', '>= 0.5.2')
21
+ spec.add_dependency('erubis')
22
+ spec.add_dependency('i18n')
23
+ spec.add_dependency('json')
24
+ spec.add_dependency('require_all', '~> 3.0')
25
+ spec.add_dependency('ruby-progressbar')
27
26
 
28
- s.add_development_dependency('awesome_print')
29
- s.add_development_dependency('bundler')
30
- s.add_development_dependency('haml')
31
- s.add_development_dependency('rake', '< 11.0')
32
- s.add_development_dependency('rspec')
33
- s.add_development_dependency('slim')
27
+ spec.add_development_dependency('awesome_print')
28
+ spec.add_development_dependency('bundler')
29
+ spec.add_development_dependency('haml')
30
+ spec.add_development_dependency('rake')
31
+ spec.add_development_dependency('rspec')
32
+ spec.add_development_dependency('slim')
34
33
 
35
- s.files = `git ls-files`.split("\n")
36
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
37
- s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
38
- s.require_paths = %w[lib assets]
34
+ spec.files = `git ls-files`.split($/)
35
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
36
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
37
+ spec.require_paths = %w[lib assets]
39
38
 
40
- s.post_install_message = <<-POST_INSTALL_MESSAGE
41
- #{'*' * 80}
39
+ spec.post_install_message = <<~POST_INSTALL_MESSAGE
40
+ #{'*' * 80}
42
41
 
43
- rails_best_practices is a code metric tool to check the quality of rails codes.
42
+ rails_best_practices is a code metric tool to check the quality of rails codes.
44
43
 
45
- I highly recommend you browse the Rails Best Practices website first.
44
+ I highly recommend you browse the Rails Best Practices website first.
46
45
 
47
- http://rails-bestpractices.com
46
+ http://rails-bestpractices.com
48
47
 
49
- Please also try our online service
48
+ Enjoy!
50
49
 
51
- http://railsbp.com
50
+ Richard Huang (flyerhzm@gmail.com)
52
51
 
53
- Enjoy!
54
-
55
- Richard Huang (flyerhzm@gmail.com)
56
-
57
- #{'*' * 80}
52
+ #{'*' * 80}
58
53
  POST_INSTALL_MESSAGE
59
54
  end