rubocop-rails 2.4.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 (69) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +20 -0
  3. data/README.md +92 -0
  4. data/bin/setup +7 -0
  5. data/config/default.yml +510 -0
  6. data/lib/rubocop-rails.rb +12 -0
  7. data/lib/rubocop/cop/mixin/target_rails_version.rb +16 -0
  8. data/lib/rubocop/cop/rails/action_filter.rb +111 -0
  9. data/lib/rubocop/cop/rails/active_record_aliases.rb +48 -0
  10. data/lib/rubocop/cop/rails/active_record_override.rb +82 -0
  11. data/lib/rubocop/cop/rails/active_support_aliases.rb +69 -0
  12. data/lib/rubocop/cop/rails/application_controller.rb +36 -0
  13. data/lib/rubocop/cop/rails/application_job.rb +40 -0
  14. data/lib/rubocop/cop/rails/application_mailer.rb +40 -0
  15. data/lib/rubocop/cop/rails/application_record.rb +40 -0
  16. data/lib/rubocop/cop/rails/assert_not.rb +44 -0
  17. data/lib/rubocop/cop/rails/belongs_to.rb +102 -0
  18. data/lib/rubocop/cop/rails/blank.rb +164 -0
  19. data/lib/rubocop/cop/rails/bulk_change_table.rb +293 -0
  20. data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +91 -0
  21. data/lib/rubocop/cop/rails/date.rb +161 -0
  22. data/lib/rubocop/cop/rails/delegate.rb +132 -0
  23. data/lib/rubocop/cop/rails/delegate_allow_blank.rb +37 -0
  24. data/lib/rubocop/cop/rails/dynamic_find_by.rb +91 -0
  25. data/lib/rubocop/cop/rails/enum_hash.rb +75 -0
  26. data/lib/rubocop/cop/rails/enum_uniqueness.rb +65 -0
  27. data/lib/rubocop/cop/rails/environment_comparison.rb +68 -0
  28. data/lib/rubocop/cop/rails/exit.rb +67 -0
  29. data/lib/rubocop/cop/rails/file_path.rb +108 -0
  30. data/lib/rubocop/cop/rails/find_by.rb +55 -0
  31. data/lib/rubocop/cop/rails/find_each.rb +51 -0
  32. data/lib/rubocop/cop/rails/has_and_belongs_to_many.rb +25 -0
  33. data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +106 -0
  34. data/lib/rubocop/cop/rails/helper_instance_variable.rb +39 -0
  35. data/lib/rubocop/cop/rails/http_positional_arguments.rb +117 -0
  36. data/lib/rubocop/cop/rails/http_status.rb +160 -0
  37. data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +94 -0
  38. data/lib/rubocop/cop/rails/inverse_of.rb +246 -0
  39. data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +175 -0
  40. data/lib/rubocop/cop/rails/link_to_blank.rb +98 -0
  41. data/lib/rubocop/cop/rails/not_null_column.rb +67 -0
  42. data/lib/rubocop/cop/rails/output.rb +49 -0
  43. data/lib/rubocop/cop/rails/output_safety.rb +99 -0
  44. data/lib/rubocop/cop/rails/pluralization_grammar.rb +107 -0
  45. data/lib/rubocop/cop/rails/presence.rb +148 -0
  46. data/lib/rubocop/cop/rails/present.rb +153 -0
  47. data/lib/rubocop/cop/rails/rake_environment.rb +91 -0
  48. data/lib/rubocop/cop/rails/read_write_attribute.rb +74 -0
  49. data/lib/rubocop/cop/rails/redundant_allow_nil.rb +111 -0
  50. data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +136 -0
  51. data/lib/rubocop/cop/rails/reflection_class_name.rb +37 -0
  52. data/lib/rubocop/cop/rails/refute_methods.rb +76 -0
  53. data/lib/rubocop/cop/rails/relative_date_constant.rb +102 -0
  54. data/lib/rubocop/cop/rails/request_referer.rb +56 -0
  55. data/lib/rubocop/cop/rails/reversible_migration.rb +284 -0
  56. data/lib/rubocop/cop/rails/safe_navigation.rb +85 -0
  57. data/lib/rubocop/cop/rails/safe_navigation_with_blank.rb +48 -0
  58. data/lib/rubocop/cop/rails/save_bang.rb +331 -0
  59. data/lib/rubocop/cop/rails/scope_args.rb +29 -0
  60. data/lib/rubocop/cop/rails/skips_model_validations.rb +87 -0
  61. data/lib/rubocop/cop/rails/time_zone.rb +249 -0
  62. data/lib/rubocop/cop/rails/uniq_before_pluck.rb +105 -0
  63. data/lib/rubocop/cop/rails/unknown_env.rb +84 -0
  64. data/lib/rubocop/cop/rails/validation.rb +147 -0
  65. data/lib/rubocop/cop/rails_cops.rb +61 -0
  66. data/lib/rubocop/rails.rb +12 -0
  67. data/lib/rubocop/rails/inject.rb +18 -0
  68. data/lib/rubocop/rails/version.rb +10 -0
  69. metadata +148 -0
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubocop'
4
+ require 'rack/utils'
5
+
6
+ require_relative 'rubocop/rails'
7
+ require_relative 'rubocop/rails/version'
8
+ require_relative 'rubocop/rails/inject'
9
+
10
+ RuboCop::Rails::Inject.defaults!
11
+
12
+ require_relative 'rubocop/cop/rails_cops'
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ # Common functionality for checking target rails version.
6
+ module TargetRailsVersion
7
+ def minimum_target_rails_version(version)
8
+ @minimum_target_rails_version = version
9
+ end
10
+
11
+ def support_target_rails_version?(version)
12
+ @minimum_target_rails_version <= version
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # This cop enforces the consistent use of action filter methods.
7
+ #
8
+ # The cop is configurable and can enforce the use of the older
9
+ # something_filter methods or the newer something_action methods.
10
+ #
11
+ # @example EnforcedStyle: action (default)
12
+ # # bad
13
+ # after_filter :do_stuff
14
+ # append_around_filter :do_stuff
15
+ # skip_after_filter :do_stuff
16
+ #
17
+ # # good
18
+ # after_action :do_stuff
19
+ # append_around_action :do_stuff
20
+ # skip_after_action :do_stuff
21
+ #
22
+ # @example EnforcedStyle: filter
23
+ # # bad
24
+ # after_action :do_stuff
25
+ # append_around_action :do_stuff
26
+ # skip_after_action :do_stuff
27
+ #
28
+ # # good
29
+ # after_filter :do_stuff
30
+ # append_around_filter :do_stuff
31
+ # skip_after_filter :do_stuff
32
+ class ActionFilter < Cop
33
+ include ConfigurableEnforcedStyle
34
+
35
+ MSG = 'Prefer `%<prefer>s` over `%<current>s`.'
36
+
37
+ FILTER_METHODS = %i[
38
+ after_filter
39
+ append_after_filter
40
+ append_around_filter
41
+ append_before_filter
42
+ around_filter
43
+ before_filter
44
+ prepend_after_filter
45
+ prepend_around_filter
46
+ prepend_before_filter
47
+ skip_after_filter
48
+ skip_around_filter
49
+ skip_before_filter
50
+ skip_filter
51
+ ].freeze
52
+
53
+ ACTION_METHODS = %i[
54
+ after_action
55
+ append_after_action
56
+ append_around_action
57
+ append_before_action
58
+ around_action
59
+ before_action
60
+ prepend_after_action
61
+ prepend_around_action
62
+ prepend_before_action
63
+ skip_after_action
64
+ skip_around_action
65
+ skip_before_action
66
+ skip_action_callback
67
+ ].freeze
68
+
69
+ def on_block(node)
70
+ check_method_node(node.send_node)
71
+ end
72
+
73
+ def on_send(node)
74
+ check_method_node(node) unless node.receiver
75
+ end
76
+
77
+ def autocorrect(node)
78
+ lambda do |corrector|
79
+ corrector.replace(node.loc.selector,
80
+ preferred_method(node.loc.selector.source).to_s)
81
+ end
82
+ end
83
+
84
+ private
85
+
86
+ def check_method_node(node)
87
+ return unless bad_methods.include?(node.method_name)
88
+
89
+ add_offense(node, location: :selector)
90
+ end
91
+
92
+ def message(node)
93
+ format(MSG, prefer: preferred_method(node.method_name),
94
+ current: node.method_name)
95
+ end
96
+
97
+ def bad_methods
98
+ style == :action ? FILTER_METHODS : ACTION_METHODS
99
+ end
100
+
101
+ def good_methods
102
+ style == :action ? ACTION_METHODS : FILTER_METHODS
103
+ end
104
+
105
+ def preferred_method(method)
106
+ good_methods[bad_methods.index(method.to_sym)]
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # Checks that ActiveRecord aliases are not used. The direct method names
7
+ # are more clear and easier to read.
8
+ #
9
+ # @example
10
+ # #bad
11
+ # Book.update_attributes!(author: 'Alice')
12
+ #
13
+ # #good
14
+ # Book.update!(author: 'Alice')
15
+ class ActiveRecordAliases < Cop
16
+ MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
17
+
18
+ ALIASES = {
19
+ update_attributes: :update,
20
+ update_attributes!: :update!
21
+ }.freeze
22
+
23
+ def on_send(node)
24
+ ALIASES.each do |bad, good|
25
+ next unless node.method?(bad)
26
+
27
+ add_offense(node,
28
+ message: format(MSG, prefer: good, current: bad),
29
+ location: :selector,
30
+ severity: :warning)
31
+ break
32
+ end
33
+ end
34
+
35
+ alias on_csend on_send
36
+
37
+ def autocorrect(node)
38
+ lambda do |corrector|
39
+ corrector.replace(
40
+ node.loc.selector,
41
+ ALIASES[node.method_name].to_s
42
+ )
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # Checks for overriding built-in Active Record methods instead of using
7
+ # callbacks.
8
+ #
9
+ # @example
10
+ # # bad
11
+ # class Book < ApplicationRecord
12
+ # def save
13
+ # self.title = title.upcase!
14
+ # super
15
+ # end
16
+ # end
17
+ #
18
+ # # good
19
+ # class Book < ApplicationRecord
20
+ # before_save :upcase_title
21
+ #
22
+ # def upcase_title
23
+ # self.title = title.upcase!
24
+ # end
25
+ # end
26
+ #
27
+ class ActiveRecordOverride < Cop
28
+ MSG =
29
+ 'Use %<prefer>s callbacks instead of overriding the Active Record ' \
30
+ 'method `%<bad>s`.'
31
+ BAD_METHODS = %i[create destroy save update].freeze
32
+ ACTIVE_RECORD_CLASSES = %w[ApplicationRecord ActiveModel::Base
33
+ ActiveRecord::Base].freeze
34
+
35
+ def on_def(node)
36
+ return unless BAD_METHODS.include?(node.method_name)
37
+
38
+ parent_class_name = find_parent_class_name(node)
39
+ return unless active_model?(parent_class_name)
40
+
41
+ return unless node.descendants.any?(&:zsuper_type?)
42
+
43
+ add_offense(node, message: message(node.method_name))
44
+ end
45
+
46
+ private
47
+
48
+ def active_model?(parent_class_name)
49
+ ACTIVE_RECORD_CLASSES.include?(parent_class_name)
50
+ end
51
+
52
+ def callback_names(method_name)
53
+ names = %w[before_ around_ after_].map do |prefix|
54
+ "`#{prefix}#{method_name}`"
55
+ end
56
+
57
+ names[-1] = "or #{names.last}"
58
+
59
+ names.join(', ')
60
+ end
61
+
62
+ def message(method_name)
63
+ format(MSG, prefer: callback_names(method_name), bad: method_name)
64
+ end
65
+
66
+ def find_parent_class_name(node)
67
+ return nil unless node
68
+
69
+ if node.class_type?
70
+ parent_class_name = node.node_parts[1]
71
+
72
+ return nil if parent_class_name.nil?
73
+
74
+ return parent_class_name.source
75
+ end
76
+
77
+ find_parent_class_name(node.parent)
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # This cop checks that ActiveSupport aliases to core ruby methods
7
+ # are not used.
8
+ #
9
+ # @example
10
+ # # good
11
+ # 'some_string'.start_with?('prefix')
12
+ # 'some_string'.end_with?('suffix')
13
+ # [1, 2, 'a'] << 'b'
14
+ # [1, 2, 'a'].unshift('b')
15
+ #
16
+ # # bad
17
+ # 'some_string'.starts_with?('prefix')
18
+ # 'some_string'.ends_with?('suffix')
19
+ # [1, 2, 'a'].append('b')
20
+ # [1, 2, 'a'].prepend('b')
21
+ #
22
+ class ActiveSupportAliases < Cop
23
+ MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
24
+
25
+ ALIASES = {
26
+ starts_with?: {
27
+ original: :start_with?, matcher: '(send str :starts_with? _)'
28
+ },
29
+ ends_with?: {
30
+ original: :end_with?, matcher: '(send str :ends_with? _)'
31
+ },
32
+ append: { original: :<<, matcher: '(send array :append _)' },
33
+ prepend: { original: :unshift, matcher: '(send array :prepend _)' }
34
+ }.freeze
35
+
36
+ ALIASES.each do |aliased_method, options|
37
+ def_node_matcher aliased_method, options[:matcher]
38
+ end
39
+
40
+ def on_send(node)
41
+ ALIASES.each_key do |aliased_method|
42
+ register_offense(node, aliased_method) if
43
+ public_send(aliased_method, node)
44
+ end
45
+ end
46
+
47
+ def autocorrect(node)
48
+ return false if append(node)
49
+
50
+ lambda do |corrector|
51
+ method_name = node.loc.selector.source
52
+ replacement = ALIASES[method_name.to_sym][:original]
53
+ corrector.replace(node.loc.selector, replacement.to_s)
54
+ end
55
+ end
56
+
57
+ private
58
+
59
+ def register_offense(node, method_name)
60
+ add_offense(
61
+ node,
62
+ message: format(MSG, prefer: ALIASES[method_name][:original],
63
+ current: method_name)
64
+ )
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # This cop checks that controllers subclass ApplicationController.
7
+ #
8
+ # @example
9
+ #
10
+ # # good
11
+ # class MyController < ApplicationController
12
+ # # ...
13
+ # end
14
+ #
15
+ # # bad
16
+ # class MyController < ActionController::Base
17
+ # # ...
18
+ # end
19
+ class ApplicationController < Cop
20
+ MSG = 'Controllers should subclass `ApplicationController`.'
21
+ SUPERCLASS = 'ApplicationController'
22
+ BASE_PATTERN = '(const (const nil? :ActionController) :Base)'
23
+
24
+ # rubocop:disable Layout/ClassStructure
25
+ include RuboCop::Cop::EnforceSuperclass
26
+ # rubocop:enable Layout/ClassStructure
27
+
28
+ def autocorrect(node)
29
+ lambda do |corrector|
30
+ corrector.replace(node.source_range, self.class::SUPERCLASS)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # This cop checks that jobs subclass ApplicationJob with Rails 5.0.
7
+ #
8
+ # @example
9
+ #
10
+ # # good
11
+ # class Rails5Job < ApplicationJob
12
+ # # ...
13
+ # end
14
+ #
15
+ # # bad
16
+ # class Rails4Job < ActiveJob::Base
17
+ # # ...
18
+ # end
19
+ class ApplicationJob < Cop
20
+ extend TargetRailsVersion
21
+
22
+ minimum_target_rails_version 5.0
23
+
24
+ MSG = 'Jobs should subclass `ApplicationJob`.'
25
+ SUPERCLASS = 'ApplicationJob'
26
+ BASE_PATTERN = '(const (const nil? :ActiveJob) :Base)'
27
+
28
+ # rubocop:disable Layout/ClassStructure
29
+ include RuboCop::Cop::EnforceSuperclass
30
+ # rubocop:enable Layout/ClassStructure
31
+
32
+ def autocorrect(node)
33
+ lambda do |corrector|
34
+ corrector.replace(node.source_range, self.class::SUPERCLASS)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # This cop checks that mailers subclass ApplicationMailer with Rails 5.0.
7
+ #
8
+ # @example
9
+ #
10
+ # # good
11
+ # class MyMailer < ApplicationMailer
12
+ # # ...
13
+ # end
14
+ #
15
+ # # bad
16
+ # class MyMailer < ActionMailer::Base
17
+ # # ...
18
+ # end
19
+ class ApplicationMailer < Cop
20
+ extend TargetRailsVersion
21
+
22
+ minimum_target_rails_version 5.0
23
+
24
+ MSG = 'Mailers should subclass `ApplicationMailer`.'
25
+ SUPERCLASS = 'ApplicationMailer'
26
+ BASE_PATTERN = '(const (const nil? :ActionMailer) :Base)'
27
+
28
+ # rubocop:disable Layout/ClassStructure
29
+ include RuboCop::Cop::EnforceSuperclass
30
+ # rubocop:enable Layout/ClassStructure
31
+
32
+ def autocorrect(node)
33
+ lambda do |corrector|
34
+ corrector.replace(node.source_range, self.class::SUPERCLASS)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end