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
@@ -11,7 +11,7 @@ module RailsBestPractices
11
11
  # Review process:
12
12
  # only check the command and command_calls nodes and at the end of review process,
13
13
  # if the receiver of command node is "create_table", then remember the table names
14
- # if the receiver of command_call node is "integer" or "string" and suffix with _id, then remember it as foreign key
14
+ # if the receiver of command_call node is "integer" or "string" or "bigint" and suffix with _id, then remember it as foreign key
15
15
  # if the receiver of command_call node is "string", the name of it is _type suffixed and there is an integer or string column _id suffixed, then remember it as polymorphic foreign key
16
16
  # if the receiver of command_call node is remembered as foreign key and it have argument non-false "index", then remember the index columns
17
17
  # if the receiver of command node is "add_index", then remember the index columns
@@ -40,9 +40,9 @@ module RailsBestPractices
40
40
  # if the message of command_call node is "create_table", then remember the table name.
41
41
  # if the message of command_call node is "add_index", then remember it as index columns.
42
42
  add_callback :start_command_call do |node|
43
- if %w[integer string].include? node.message.to_s
43
+ if %w[integer string bigint].include? node.message.to_s
44
44
  remember_foreign_key_columns(node)
45
- elsif 'index' == node.message.to_s
45
+ elsif node.message.to_s == 'index'
46
46
  remember_index_columns_inside_table(node)
47
47
  end
48
48
  end
@@ -75,120 +75,125 @@ module RailsBestPractices
75
75
  @foreign_keys.each do |table, foreign_key|
76
76
  table_node = @table_nodes[table]
77
77
  foreign_key.each do |column|
78
- if not_indexed?(table, column)
79
- add_error "always add db index (#{table} => [#{Array(column).join(', ')}])", table_node.file, table_node.line_number
80
- end
78
+ next unless not_indexed?(table, column)
79
+
80
+ add_error "always add db index (#{table} => [#{Array(column).join(', ')}])",
81
+ table_node.file,
82
+ table_node.line_number
81
83
  end
82
84
  end
83
85
  end
84
86
 
85
87
  private
86
88
 
87
- # remember the node as index columns, when used outside a table
88
- # block, i.e.
89
- # add_index :table_name, :column_name
90
- def remember_index_columns_outside_table(node)
91
- table_name = node.arguments.all.first.to_s
92
- index_column = node.arguments.all[1].to_object
89
+ # remember the node as index columns, when used outside a table
90
+ # block, i.e.
91
+ # add_index :table_name, :column_name
92
+ def remember_index_columns_outside_table(node)
93
+ table_name = node.arguments.all.first.to_s
94
+ index_column = node.arguments.all[1].to_object
93
95
 
94
- @index_columns[table_name] ||= []
95
- @index_columns[table_name] << index_column
96
- end
96
+ @index_columns[table_name] ||= []
97
+ @index_columns[table_name] << index_column
98
+ end
97
99
 
98
- # remember the node as index columns, when used inside a table
99
- # block, i.e.
100
- # t.index [:column_name, ...]
101
- def remember_index_columns_inside_table(node)
102
- table_name = @table_name
103
- index_column = node.arguments.all.first.to_object
100
+ # remember the node as index columns, when used inside a table
101
+ # block, i.e.
102
+ # t.index [:column_name, ...]
103
+ def remember_index_columns_inside_table(node)
104
+ table_name = @table_name
105
+ index_column = node.arguments.all.first.to_object
104
106
 
105
- @index_columns[table_name] ||= []
106
- @index_columns[table_name] << index_column
107
- end
107
+ @index_columns[table_name] ||= []
108
+ @index_columns[table_name] << index_column
109
+ end
108
110
 
109
- # remember table nodes
110
- def remember_table_nodes(node)
111
- @table_name = node.arguments.all.first.to_s
112
- @table_nodes[@table_name] = node
113
- end
111
+ # remember table nodes
112
+ def remember_table_nodes(node)
113
+ @table_name = node.arguments.all.first.to_s
114
+ @table_nodes[@table_name] = node
115
+ end
114
116
 
115
- # remember foreign key columns
116
- def remember_foreign_key_columns(node)
117
- table_name = @table_name
118
- foreign_key_column = node.arguments.all.first.to_s
119
- @foreign_keys[table_name] ||= []
120
- if foreign_key_column =~ /(.*?)_id$/
121
- if @foreign_keys[table_name].delete("#{$1}_type")
122
- @foreign_keys[table_name] << ["#{$1}_id", "#{$1}_type"]
117
+ # remember foreign key columns
118
+ def remember_foreign_key_columns(node)
119
+ table_name = @table_name
120
+ foreign_key_column = node.arguments.all.first.to_s
121
+ @foreign_keys[table_name] ||= []
122
+ if foreign_key_column =~ /(.*?)_id$/
123
+ @foreign_keys[table_name] <<
124
+ if @foreign_keys[table_name].delete("#{Regexp.last_match(1)}_type")
125
+ ["#{Regexp.last_match(1)}_id", "#{Regexp.last_match(1)}_type"]
123
126
  else
124
- @foreign_keys[table_name] << foreign_key_column
127
+ foreign_key_column
125
128
  end
126
- foreign_id_column = foreign_key_column
127
- elsif foreign_key_column =~ /(.*?)_type$/
128
- if @foreign_keys[table_name].delete("#{$1}_id")
129
- @foreign_keys[table_name] << ["#{$1}_id", "#{$1}_type"]
129
+ foreign_id_column = foreign_key_column
130
+ elsif foreign_key_column =~ /(.*?)_type$/
131
+ @foreign_keys[table_name] <<
132
+ if @foreign_keys[table_name].delete("#{Regexp.last_match(1)}_id")
133
+ ["#{Regexp.last_match(1)}_id", "#{Regexp.last_match(1)}_type"]
130
134
  else
131
- @foreign_keys[table_name] << foreign_key_column
135
+ foreign_key_column
132
136
  end
133
- foreign_id_column = "#{$1}_id"
134
- end
137
+ foreign_id_column = "#{Regexp.last_match(1)}_id"
138
+ end
135
139
 
136
- if foreign_id_column
137
- index_node = node.arguments.all.last.hash_value('index')
138
- if index_node.present? && ('false' != index_node.to_s)
139
- @index_columns[table_name] ||= []
140
- @index_columns[table_name] << foreign_id_column
141
- end
140
+ if foreign_id_column
141
+ index_node = node.arguments.all.last.hash_value('index')
142
+ if index_node.present? && (index_node.to_s != 'false')
143
+ @index_columns[table_name] ||= []
144
+ @index_columns[table_name] << foreign_id_column
142
145
  end
143
146
  end
147
+ end
144
148
 
145
- # remove the non foreign keys without corresponding tables.
146
- def remove_table_not_exist_foreign_keys
147
- @foreign_keys.each do |table, foreign_keys|
148
- foreign_keys.delete_if do |key|
149
- if key =~ /_id$/
150
- class_name = Prepares.model_associations.get_association_class_name(table, key[0..-4])
151
- class_name ? !@table_nodes[class_name.gsub('::', '').tableize] : !@table_nodes[key[0..-4].pluralize]
152
- end
149
+ # remove the non foreign keys without corresponding tables.
150
+ def remove_table_not_exist_foreign_keys
151
+ @foreign_keys.each do |table, foreign_keys|
152
+ foreign_keys.delete_if do |key|
153
+ if key.is_a?(String) && key =~ /_id$/
154
+ class_name = Prepares.model_associations.get_association_class_name(table, key[0..-4])
155
+ class_name ? !@table_nodes[class_name.gsub('::', '').tableize] : !@table_nodes[key[0..-4].pluralize]
153
156
  end
154
157
  end
155
158
  end
159
+ end
156
160
 
157
- # remove the non foreign keys with only _type column.
158
- def remove_only_type_foreign_keys
159
- @foreign_keys.each { |_table, foreign_keys|
160
- foreign_keys.delete_if { |key| key =~ /_type$/ }
161
- }
161
+ # remove the non foreign keys with only _type column.
162
+ def remove_only_type_foreign_keys
163
+ @foreign_keys.each do |_table, foreign_keys|
164
+ foreign_keys.delete_if { |key| key.is_a?(String) && key =~ /_type$/ }
162
165
  end
166
+ end
163
167
 
164
- # combine polymorphic foreign keys, e.g.
165
- # [tagger_id], [tagger_type] => [tagger_id, tagger_type]
166
- def combine_polymorphic_foreign_keys
167
- @index_columns.each { |_table, foreign_keys|
168
- foreign_id_keys = foreign_keys.select { |key| key.size == 1 && key.first =~ /_id/ }
169
- foreign_type_keys = foreign_keys.select { |key| key.size == 1 && key.first =~ /_type/ }
170
- foreign_id_keys.each do |id_key|
171
- if type_key = foreign_type_keys.detect { |type_key| type_key.first == id_key.first.sub(/_id/, '') + '_type' }
172
- foreign_keys.delete(id_key)
173
- foreign_keys.delete(type_key)
174
- foreign_keys << id_key + type_key
175
- end
176
- end
177
- }
168
+ # combine polymorphic foreign keys, e.g.
169
+ # [tagger_id], [tagger_type] => [tagger_id, tagger_type]
170
+ def combine_polymorphic_foreign_keys
171
+ @index_columns.each do |_table, foreign_keys|
172
+ foreign_id_keys = foreign_keys.select { |key| key.size == 1 && key.first =~ /_id/ }
173
+ foreign_type_keys = foreign_keys.select { |key| key.size == 1 && key.first =~ /_type/ }
174
+ foreign_id_keys.each do |id_key|
175
+ next unless type_key =
176
+ foreign_type_keys.detect { |type_key| type_key.first == id_key.first.sub(/_id/, '') + '_type' }
177
+
178
+ foreign_keys.delete(id_key)
179
+ foreign_keys.delete(type_key)
180
+ foreign_keys << id_key + type_key
181
+ end
178
182
  end
183
+ end
179
184
 
180
- # check if the table's column is indexed.
181
- def not_indexed?(table, column)
182
- index_columns = @index_columns[table]
183
- !index_columns || index_columns.none? { |e| greater_than_or_equal(Array(e), Array(column)) }
184
- end
185
+ # check if the table's column is indexed.
186
+ def not_indexed?(table, column)
187
+ index_columns = @index_columns[table]
188
+ !index_columns || index_columns.none? { |e| greater_than_or_equal(Array(e), Array(column)) }
189
+ end
185
190
 
186
- # check if more_array is greater than less_array or equal to less_array.
187
- def greater_than_or_equal(more_array, less_array)
188
- more_size = more_array.size
189
- less_size = less_array.size
190
- (more_array - less_array).size == more_size - less_size
191
- end
191
+ # check if more_array is greater than less_array or equal to less_array.
192
+ def greater_than_or_equal(more_array, less_array)
193
+ more_size = more_array.size
194
+ less_size = less_array.size
195
+ (more_array - less_array).size == more_size - less_size
196
+ end
192
197
  end
193
198
  end
194
199
  end
@@ -10,7 +10,17 @@ module RailsBestPractices
10
10
  # Check all "save" calls to check the return value is used by a node we have visited.
11
11
  class CheckDestroyReturnValueReview < Review
12
12
  include Classable
13
- interesting_nodes :call, :command_call, :method_add_arg, :if, :ifop, :elsif, :unless, :if_mod, :unless_mod, :assign, :binary
13
+ interesting_nodes :call,
14
+ :command_call,
15
+ :method_add_arg,
16
+ :if,
17
+ :ifop,
18
+ :elsif,
19
+ :unless,
20
+ :if_mod,
21
+ :unless_mod,
22
+ :assign,
23
+ :binary
14
24
  interesting_files ALL_FILES
15
25
 
16
26
  add_callback :start_if, :start_ifop, :start_elsif, :start_unless, :start_if_mod, :start_unless_mod do |node|
@@ -21,14 +31,13 @@ module RailsBestPractices
21
31
  @used_return_value_of = node.right_value
22
32
  end
23
33
 
34
+ # Consider anything used in an expression like "A or B" as used
24
35
  add_callback :start_binary do |node|
25
- # Consider anything used in an expression like "A or B" as used
26
36
  if %w[&& || and or].include?(node[2].to_s)
27
37
  all_conditions = node.all_conditions
28
38
  # if our current binary is a subset of the @used_return_value_of
29
39
  # then don't overwrite it
30
- already_included = @used_return_value_of &&
31
- (all_conditions - @used_return_value_of).empty?
40
+ already_included = @used_return_value_of && (all_conditions - @used_return_value_of).empty?
32
41
 
33
42
  @used_return_value_of = node.all_conditions unless already_included
34
43
  end
@@ -36,7 +45,8 @@ module RailsBestPractices
36
45
 
37
46
  def return_value_is_used?(node)
38
47
  return false unless @used_return_value_of
39
- node == @used_return_value_of or @used_return_value_of.include?(node)
48
+
49
+ (node == @used_return_value_of) || @used_return_value_of.include?(node)
40
50
  end
41
51
 
42
52
  def model_classnames
@@ -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