rubocop-rails 2.12.1 → 2.13.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/config/default.yml +43 -8
- data/lib/rubocop/cop/mixin/active_record_migrations_helper.rb +34 -0
- data/lib/rubocop/cop/rails/active_record_aliases.rb +6 -2
- data/lib/rubocop/cop/rails/application_controller.rb +5 -1
- data/lib/rubocop/cop/rails/application_job.rb +5 -1
- data/lib/rubocop/cop/rails/application_mailer.rb +5 -1
- data/lib/rubocop/cop/rails/application_record.rb +6 -1
- data/lib/rubocop/cop/rails/arel_star.rb +6 -0
- data/lib/rubocop/cop/rails/blank.rb +5 -4
- data/lib/rubocop/cop/rails/compact_blank.rb +98 -0
- data/lib/rubocop/cop/rails/content_tag.rb +15 -8
- data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +2 -7
- data/lib/rubocop/cop/rails/duration_arithmetic.rb +97 -0
- data/lib/rubocop/cop/rails/dynamic_find_by.rb +4 -0
- data/lib/rubocop/cop/rails/find_each.rb +13 -0
- data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +1 -1
- data/lib/rubocop/cop/rails/http_positional_arguments.rb +1 -1
- data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +8 -7
- data/lib/rubocop/cop/rails/mailer_name.rb +4 -0
- data/lib/rubocop/cop/rails/negate_include.rb +3 -2
- data/lib/rubocop/cop/rails/output.rb +4 -0
- data/lib/rubocop/cop/rails/pick.rb +7 -0
- data/lib/rubocop/cop/rails/pluck_id.rb +3 -0
- data/lib/rubocop/cop/rails/pluck_in_where.rb +7 -6
- data/lib/rubocop/cop/rails/rake_environment.rb +5 -0
- data/lib/rubocop/cop/rails/redundant_presence_validation_on_belongs_to.rb +192 -0
- data/lib/rubocop/cop/rails/reflection_class_name.rb +4 -2
- data/lib/rubocop/cop/rails/relative_date_constant.rb +4 -1
- data/lib/rubocop/cop/rails/reversible_migration.rb +11 -3
- data/lib/rubocop/cop/rails/root_join_chain.rb +72 -0
- data/lib/rubocop/cop/rails/safe_navigation_with_blank.rb +12 -3
- data/lib/rubocop/cop/rails/save_bang.rb +19 -0
- data/lib/rubocop/cop/rails/schema_comment.rb +104 -0
- data/lib/rubocop/cop/rails/squished_sql_heredocs.rb +4 -2
- data/lib/rubocop/cop/rails/time_zone.rb +3 -0
- data/lib/rubocop/cop/rails/uniq_before_pluck.rb +29 -35
- data/lib/rubocop/cop/rails/unique_validation_without_index.rb +1 -1
- data/lib/rubocop/cop/rails/where_equals.rb +4 -0
- data/lib/rubocop/cop/rails/where_exists.rb +9 -8
- data/lib/rubocop/cop/rails_cops.rb +6 -0
- data/lib/rubocop/rails/version.rb +1 -1
- metadata +11 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f12ec262c68bd72f514b80f2140b51278a947f21726ef6307e6267eaec7df4ae
|
4
|
+
data.tar.gz: 2a09b4db338465d1904a19e8d4af871ba485e75244613299fabe473854125e4c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fbf73dc2e978bc210e2dc190b8042720f24e6e374962b2873e6c29ec989ed2a7c1b05646c22a38d57f28e753104ac40a0e592730e63703d99dbb80fc6b498651
|
7
|
+
data.tar.gz: b70e78355a3fa5b09f3a2a1603c71b16547c3f2f80c0ce7c2dbbc3c38cae0a0ca9464a50895eb54ac8ccd558c9259bf28a1e4ebebb9e3d4f05102832f178fc11
|
data/config/default.yml
CHANGED
@@ -9,7 +9,7 @@ AllCops:
|
|
9
9
|
- bin/*
|
10
10
|
- db/schema.rb
|
11
11
|
# What version of Rails is the inspected code using? If a value is specified
|
12
|
-
# for TargetRailsVersion then it is used. Acceptable values are
|
12
|
+
# for TargetRailsVersion then it is used. Acceptable values are specified
|
13
13
|
# as a float (i.e. 5.1); the patch version of Rails should not be included.
|
14
14
|
# If TargetRailsVersion is not set, RuboCop will parse the Gemfile.lock or
|
15
15
|
# gems.locked file to find the version of Rails that has been bound to the
|
@@ -180,6 +180,12 @@ Rails/BulkChangeTable:
|
|
180
180
|
Include:
|
181
181
|
- db/migrate/*.rb
|
182
182
|
|
183
|
+
Rails/CompactBlank:
|
184
|
+
Description: 'Checks if collection can be blank-compacted with `compact_blank`.'
|
185
|
+
Enabled: pending
|
186
|
+
Safe: false
|
187
|
+
VersionAdded: '2.13'
|
188
|
+
|
183
189
|
Rails/ContentTag:
|
184
190
|
Description: 'Use `tag.something` instead of `tag(:something)`.'
|
185
191
|
Reference:
|
@@ -189,6 +195,9 @@ Rails/ContentTag:
|
|
189
195
|
Enabled: true
|
190
196
|
VersionAdded: '2.6'
|
191
197
|
VersionChanged: '2.12'
|
198
|
+
# This `Exclude` config prevents false positives for `tag` calls to `has_one: tag`. No helpers are used in normal models.
|
199
|
+
Exclude:
|
200
|
+
- app/models/**/*.rb
|
192
201
|
|
193
202
|
Rails/CreateTableWithTimestamps:
|
194
203
|
Description: >-
|
@@ -198,6 +207,10 @@ Rails/CreateTableWithTimestamps:
|
|
198
207
|
VersionAdded: '0.52'
|
199
208
|
Include:
|
200
209
|
- db/migrate/*.rb
|
210
|
+
Exclude:
|
211
|
+
# Respect the `active_storage_variant_records` table of `*_create_active_storage_tables.active_storage.rb`
|
212
|
+
# auto-generated by `bin/rails active_storage:install` even if `created_at` is not specified.
|
213
|
+
- db/migrate/*_create_active_storage_tables.active_storage.rb
|
201
214
|
|
202
215
|
Rails/Date:
|
203
216
|
Description: >-
|
@@ -238,6 +251,12 @@ Rails/DelegateAllowBlank:
|
|
238
251
|
Enabled: true
|
239
252
|
VersionAdded: '0.44'
|
240
253
|
|
254
|
+
Rails/DurationArithmetic:
|
255
|
+
Description: 'Do not use duration as arithmetic operand with `Time.current`.'
|
256
|
+
StyleGuide: 'https://rails.rubystyle.guide#duration-arithmetic'
|
257
|
+
Enabled: pending
|
258
|
+
VersionAdded: '2.13'
|
259
|
+
|
241
260
|
Rails/DynamicFindBy:
|
242
261
|
Description: 'Use `find_by` instead of dynamic `find_by_*`.'
|
243
262
|
StyleGuide: 'https://rails.rubystyle.guide#find_by'
|
@@ -605,6 +624,11 @@ Rails/RedundantForeignKey:
|
|
605
624
|
Enabled: true
|
606
625
|
VersionAdded: '2.6'
|
607
626
|
|
627
|
+
Rails/RedundantPresenceValidationOnBelongsTo:
|
628
|
+
Description: 'Checks for redundant presence validation on belongs_to association.'
|
629
|
+
Enabled: pending
|
630
|
+
VersionAdded: '2.13'
|
631
|
+
|
608
632
|
Rails/RedundantReceiverInWithOptions:
|
609
633
|
Description: 'Checks for redundant receiver in `with_options`.'
|
610
634
|
Enabled: true
|
@@ -639,9 +663,9 @@ Rails/RefuteMethods:
|
|
639
663
|
Rails/RelativeDateConstant:
|
640
664
|
Description: 'Do not assign relative date to constants.'
|
641
665
|
Enabled: true
|
666
|
+
SafeAutoCorrect: false
|
642
667
|
VersionAdded: '0.48'
|
643
|
-
VersionChanged: '
|
644
|
-
AutoCorrect: false
|
668
|
+
VersionChanged: '2.13'
|
645
669
|
|
646
670
|
Rails/RenderInline:
|
647
671
|
Description: 'Prefer using a template over inline rendering.'
|
@@ -688,6 +712,11 @@ Rails/ReversibleMigrationMethodDefinition:
|
|
688
712
|
Include:
|
689
713
|
- db/migrate/*.rb
|
690
714
|
|
715
|
+
Rails/RootJoinChain:
|
716
|
+
Description: 'Use a single `#join` instead of chaining on `Rails.root` or `Rails.public_path`.'
|
717
|
+
Enabled: pending
|
718
|
+
VersionAdded: '2.13'
|
719
|
+
|
691
720
|
Rails/SafeNavigation:
|
692
721
|
Description: "Use Ruby's safe navigation operator (`&.`) instead of `try!`."
|
693
722
|
Enabled: true
|
@@ -720,6 +749,13 @@ Rails/SaveBang:
|
|
720
749
|
AllowedReceivers: []
|
721
750
|
SafeAutoCorrect: false
|
722
751
|
|
752
|
+
Rails/SchemaComment:
|
753
|
+
Description: >-
|
754
|
+
This cop enforces the use of the `comment` option when adding a new table or column
|
755
|
+
to the database during a migration.
|
756
|
+
Enabled: false
|
757
|
+
VersionAdded: '2.13'
|
758
|
+
|
723
759
|
Rails/ScopeArgs:
|
724
760
|
Description: 'Checks the arguments of ActiveRecord scopes.'
|
725
761
|
Enabled: true
|
@@ -782,9 +818,9 @@ Rails/TimeZone:
|
|
782
818
|
StyleGuide: 'https://rails.rubystyle.guide#time'
|
783
819
|
Reference: 'http://danilenko.org/2012/7/6/rails_timezones'
|
784
820
|
Enabled: true
|
785
|
-
|
821
|
+
SafeAutoCorrect: false
|
786
822
|
VersionAdded: '0.30'
|
787
|
-
VersionChanged: '2.
|
823
|
+
VersionChanged: '2.13'
|
788
824
|
# The value `strict` means that `Time` should be used with `zone`.
|
789
825
|
# The value `flexible` allows usage of `in_time_zone` instead of `zone`.
|
790
826
|
EnforcedStyle: flexible
|
@@ -807,16 +843,15 @@ Rails/UniqBeforePluck:
|
|
807
843
|
Description: 'Prefer the use of uniq or distinct before pluck.'
|
808
844
|
Enabled: true
|
809
845
|
VersionAdded: '0.40'
|
810
|
-
VersionChanged: '2.
|
846
|
+
VersionChanged: '2.13'
|
811
847
|
EnforcedStyle: conservative
|
812
848
|
SupportedStyles:
|
813
849
|
- conservative
|
814
850
|
- aggressive
|
815
851
|
SafeAutoCorrect: false
|
816
|
-
AutoCorrect: false
|
817
852
|
|
818
853
|
Rails/UniqueValidationWithoutIndex:
|
819
|
-
Description: 'Uniqueness validation should
|
854
|
+
Description: 'Uniqueness validation should have a unique index on the database column.'
|
820
855
|
Enabled: true
|
821
856
|
VersionAdded: '2.5'
|
822
857
|
Include:
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
# A mixin to extend cops for Active Record features
|
6
|
+
module ActiveRecordMigrationsHelper
|
7
|
+
extend NodePattern::Macros
|
8
|
+
|
9
|
+
RAILS_ABSTRACT_SCHEMA_DEFINITIONS = %i[
|
10
|
+
bigint binary boolean date datetime decimal float integer json string
|
11
|
+
text time timestamp virtual
|
12
|
+
].freeze
|
13
|
+
RAILS_ABSTRACT_SCHEMA_DEFINITIONS_HELPERS = %i[
|
14
|
+
column references belongs_to primary_key numeric
|
15
|
+
].freeze
|
16
|
+
POSTGRES_SCHEMA_DEFINITIONS = %i[
|
17
|
+
bigserial bit bit_varying cidr citext daterange hstore inet interval
|
18
|
+
int4range int8range jsonb ltree macaddr money numrange oid point line
|
19
|
+
lseg box path polygon circle serial tsrange tstzrange tsvector uuid xml
|
20
|
+
].freeze
|
21
|
+
MYSQL_SCHEMA_DEFINITIONS = %i[
|
22
|
+
blob tinyblob mediumblob longblob tinytext mediumtext longtext
|
23
|
+
unsigned_integer unsigned_bigint unsigned_float unsigned_decimal
|
24
|
+
].freeze
|
25
|
+
|
26
|
+
def_node_matcher :create_table_with_block?, <<~PATTERN
|
27
|
+
(block
|
28
|
+
(send nil? :create_table ...)
|
29
|
+
(args (arg _var))
|
30
|
+
_)
|
31
|
+
PATTERN
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -6,12 +6,16 @@ module RuboCop
|
|
6
6
|
# Checks that ActiveRecord aliases are not used. The direct method names
|
7
7
|
# are more clear and easier to read.
|
8
8
|
#
|
9
|
+
# @safety
|
10
|
+
# This cop is unsafe because custom `update_attributes` method call was changed to
|
11
|
+
# `update` but the method name remained same in the method definition.
|
12
|
+
#
|
9
13
|
# @example
|
10
14
|
# #bad
|
11
|
-
#
|
15
|
+
# book.update_attributes!(author: 'Alice')
|
12
16
|
#
|
13
17
|
# #good
|
14
|
-
#
|
18
|
+
# book.update!(author: 'Alice')
|
15
19
|
class ActiveRecordAliases < Base
|
16
20
|
extend AutoCorrector
|
17
21
|
|
@@ -3,7 +3,11 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Rails
|
6
|
-
# This cop checks that controllers subclass ApplicationController
|
6
|
+
# This cop checks that controllers subclass `ApplicationController`.
|
7
|
+
#
|
8
|
+
# @safety
|
9
|
+
# This cop's autocorrection is unsafe because it may let the logic from `ApplicationController`
|
10
|
+
# sneak into a controller that is not purposed to inherit logic common among other controllers.
|
7
11
|
#
|
8
12
|
# @example
|
9
13
|
#
|
@@ -3,7 +3,11 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Rails
|
6
|
-
# This cop checks that jobs subclass ApplicationJob with Rails 5.0.
|
6
|
+
# This cop checks that jobs subclass `ApplicationJob` with Rails 5.0.
|
7
|
+
#
|
8
|
+
# @safety
|
9
|
+
# This cop's autocorrection is unsafe because it may let the logic from `ApplicationJob`
|
10
|
+
# sneak into a job that is not purposed to inherit logic common among other jobs.
|
7
11
|
#
|
8
12
|
# @example
|
9
13
|
#
|
@@ -3,7 +3,11 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Rails
|
6
|
-
# This cop checks that mailers subclass ApplicationMailer with Rails 5.0.
|
6
|
+
# This cop checks that mailers subclass `ApplicationMailer` with Rails 5.0.
|
7
|
+
#
|
8
|
+
# @safety
|
9
|
+
# This cop's autocorrection is unsafe because it may let the logic from `ApplicationMailer`
|
10
|
+
# sneak into a mailer that is not purposed to inherit logic common among other mailers.
|
7
11
|
#
|
8
12
|
# @example
|
9
13
|
#
|
@@ -3,7 +3,12 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Rails
|
6
|
-
# This cop checks that models subclass ApplicationRecord with Rails 5.0.
|
6
|
+
# This cop checks that models subclass `ApplicationRecord` with Rails 5.0.
|
7
|
+
#
|
8
|
+
# @safety
|
9
|
+
# This cop's autocorrection is unsafe because it may let the logic from `ApplicationRecord`
|
10
|
+
# sneak into an Active Record model that is not purposed to inherit logic common among other
|
11
|
+
# Active Record models.
|
7
12
|
#
|
8
13
|
# @example
|
9
14
|
#
|
@@ -10,6 +10,12 @@ module RuboCop
|
|
10
10
|
# database to look for a column named <tt>`*`</tt> (or `"*"`) as opposed
|
11
11
|
# to expanding the column list as one would likely expect.
|
12
12
|
#
|
13
|
+
# @safety
|
14
|
+
# This cop's autocorrection is unsafe because it turns a quoted `*` into
|
15
|
+
# an SQL `*`, unquoted. `*` is a valid column name in certain databases
|
16
|
+
# supported by Rails, and even though it is usually a mistake,
|
17
|
+
# it might denote legitimate access to a column named `*`.
|
18
|
+
#
|
13
19
|
# @example
|
14
20
|
# # bad
|
15
21
|
# MyTable.arel_table["*"]
|
@@ -6,15 +6,16 @@ module RuboCop
|
|
6
6
|
# This cop checks for code that can be written with simpler conditionals
|
7
7
|
# using `Object#blank?` defined by Active Support.
|
8
8
|
#
|
9
|
-
# This cop is marked as unsafe auto-correction, because `' '.empty?` returns false,
|
10
|
-
# but `' '.blank?` returns true. Therefore, auto-correction is not compatible
|
11
|
-
# if the receiver is a non-empty blank string, tab, or newline meta characters.
|
12
|
-
#
|
13
9
|
# Interaction with `Style/UnlessElse`:
|
14
10
|
# The configuration of `NotPresent` will not produce an offense in the
|
15
11
|
# context of `unless else` if `Style/UnlessElse` is inabled. This is
|
16
12
|
# to prevent interference between the auto-correction of the two cops.
|
17
13
|
#
|
14
|
+
# @safety
|
15
|
+
# This cop is unsafe auto-correction, because `' '.empty?` returns false,
|
16
|
+
# but `' '.blank?` returns true. Therefore, auto-correction is not compatible
|
17
|
+
# if the receiver is a non-empty blank string, tab, or newline meta characters.
|
18
|
+
#
|
18
19
|
# @example NilOrEmpty: true (default)
|
19
20
|
# # Converts usages of `nil? || empty?` to `blank?`
|
20
21
|
#
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# Checks if collection can be blank-compacted with `compact_blank`.
|
7
|
+
#
|
8
|
+
# @safety
|
9
|
+
# It is unsafe by default because false positives may occur in the
|
10
|
+
# blank check of block arguments to the receiver object.
|
11
|
+
#
|
12
|
+
# For example, `[[1, 2], [3, nil]].reject { |first, second| second.blank? }` and
|
13
|
+
# `[[1, 2], [3, nil]].compact_blank` are not compatible. The same is true for `empty?`.
|
14
|
+
# This will work fine when the receiver is a hash object.
|
15
|
+
#
|
16
|
+
# @example
|
17
|
+
#
|
18
|
+
# # bad
|
19
|
+
# collection.reject(&:blank?)
|
20
|
+
# collection.reject(&:empty?)
|
21
|
+
# collection.reject { |_k, v| v.blank? }
|
22
|
+
# collection.reject { |_k, v| v.empty? }
|
23
|
+
#
|
24
|
+
# # good
|
25
|
+
# collection.compact_blank
|
26
|
+
#
|
27
|
+
# # bad
|
28
|
+
# collection.reject!(&:blank?)
|
29
|
+
# collection.reject!(&:empty?)
|
30
|
+
# collection.reject! { |_k, v| v.blank? }
|
31
|
+
# collection.reject! { |_k, v| v.empty? }
|
32
|
+
#
|
33
|
+
# # good
|
34
|
+
# collection.compact_blank!
|
35
|
+
#
|
36
|
+
class CompactBlank < Base
|
37
|
+
include RangeHelp
|
38
|
+
extend AutoCorrector
|
39
|
+
extend TargetRailsVersion
|
40
|
+
|
41
|
+
MSG = 'Use `%<preferred_method>s` instead.'
|
42
|
+
RESTRICT_ON_SEND = %i[reject reject!].freeze
|
43
|
+
|
44
|
+
minimum_target_rails_version 6.1
|
45
|
+
|
46
|
+
def_node_matcher :reject_with_block?, <<~PATTERN
|
47
|
+
(block
|
48
|
+
(send _ {:reject :reject!})
|
49
|
+
$(args ...)
|
50
|
+
(send
|
51
|
+
$(lvar _) {:blank? :empty?}))
|
52
|
+
PATTERN
|
53
|
+
|
54
|
+
def_node_matcher :reject_with_block_pass?, <<~PATTERN
|
55
|
+
(send _ {:reject :reject!}
|
56
|
+
(block_pass
|
57
|
+
(sym {:blank? :empty?})))
|
58
|
+
PATTERN
|
59
|
+
|
60
|
+
def on_send(node)
|
61
|
+
return unless bad_method?(node)
|
62
|
+
|
63
|
+
range = offense_range(node)
|
64
|
+
preferred_method = preferred_method(node)
|
65
|
+
add_offense(range, message: format(MSG, preferred_method: preferred_method)) do |corrector|
|
66
|
+
corrector.replace(range, preferred_method)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def bad_method?(node)
|
73
|
+
return true if reject_with_block_pass?(node)
|
74
|
+
|
75
|
+
if (arguments, receiver_in_block = reject_with_block?(node.parent))
|
76
|
+
return arguments.length == 1 || use_hash_value_block_argument?(arguments, receiver_in_block)
|
77
|
+
end
|
78
|
+
|
79
|
+
false
|
80
|
+
end
|
81
|
+
|
82
|
+
def use_hash_value_block_argument?(arguments, receiver_in_block)
|
83
|
+
arguments.length == 2 && arguments[1].source == receiver_in_block.source
|
84
|
+
end
|
85
|
+
|
86
|
+
def offense_range(node)
|
87
|
+
end_pos = node.parent&.block_type? ? node.parent.loc.expression.end_pos : node.loc.expression.end_pos
|
88
|
+
|
89
|
+
range_between(node.loc.selector.begin_pos, end_pos)
|
90
|
+
end
|
91
|
+
|
92
|
+
def preferred_method(node)
|
93
|
+
node.method?(:reject) ? 'compact_blank' : 'compact_blank!'
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -6,8 +6,8 @@ module RuboCop
|
|
6
6
|
# This cop checks legacy syntax usage of `tag`
|
7
7
|
#
|
8
8
|
# NOTE: Allow `tag` when the first argument is a variable because
|
9
|
-
#
|
10
|
-
#
|
9
|
+
# `tag(name)` is simpler rather than `tag.public_send(name)`.
|
10
|
+
# And this cop will be renamed to something like `LegacyTag` in the future. (e.g. RuboCop Rails 2.0)
|
11
11
|
#
|
12
12
|
# @example
|
13
13
|
# # bad
|
@@ -33,6 +33,9 @@ module RuboCop
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def on_send(node)
|
36
|
+
return unless node.receiver.nil?
|
37
|
+
return if node.arguments.count >= 3
|
38
|
+
|
36
39
|
first_argument = node.first_argument
|
37
40
|
return if !first_argument ||
|
38
41
|
allowed_argument?(first_argument) ||
|
@@ -41,12 +44,7 @@ module RuboCop
|
|
41
44
|
preferred_method = node.first_argument.value.to_s.underscore
|
42
45
|
message = format(MSG, preferred_method: preferred_method, current_argument: first_argument.source)
|
43
46
|
|
44
|
-
|
45
|
-
autocorrect(corrector, node, preferred_method)
|
46
|
-
|
47
|
-
@corrected_nodes ||= Set.new.compare_by_identity
|
48
|
-
@corrected_nodes.add(node)
|
49
|
-
end
|
47
|
+
register_offense(node, message, preferred_method)
|
50
48
|
end
|
51
49
|
|
52
50
|
private
|
@@ -63,6 +61,15 @@ module RuboCop
|
|
63
61
|
allowed_name?(argument)
|
64
62
|
end
|
65
63
|
|
64
|
+
def register_offense(node, message, preferred_method)
|
65
|
+
add_offense(node, message: message) do |corrector|
|
66
|
+
autocorrect(corrector, node, preferred_method)
|
67
|
+
|
68
|
+
@corrected_nodes ||= Set.new.compare_by_identity
|
69
|
+
@corrected_nodes.add(node)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
66
73
|
def autocorrect(corrector, node, preferred_method)
|
67
74
|
range = correction_range(node)
|
68
75
|
|
@@ -41,16 +41,11 @@ module RuboCop
|
|
41
41
|
# t.datetime :updated_at, default: -> { 'CURRENT_TIMESTAMP' }
|
42
42
|
# end
|
43
43
|
class CreateTableWithTimestamps < Base
|
44
|
+
include ActiveRecordMigrationsHelper
|
45
|
+
|
44
46
|
MSG = 'Add timestamps when creating a new table.'
|
45
47
|
RESTRICT_ON_SEND = %i[create_table].freeze
|
46
48
|
|
47
|
-
def_node_matcher :create_table_with_block?, <<~PATTERN
|
48
|
-
(block
|
49
|
-
(send nil? :create_table ...)
|
50
|
-
(args (arg _var))
|
51
|
-
_)
|
52
|
-
PATTERN
|
53
|
-
|
54
49
|
def_node_matcher :create_table_with_timestamps_proc?, <<~PATTERN
|
55
50
|
(send nil? :create_table (sym _) ... (block-pass (sym :timestamps)))
|
56
51
|
PATTERN
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop checks if a duration is added to or subtracted from `Time.current`.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# Time.current - 1.minute
|
11
|
+
# Time.current + 2.days
|
12
|
+
#
|
13
|
+
# # good - using relative would make it harder to express and read
|
14
|
+
# Date.yesterday + 3.days
|
15
|
+
# created_at - 1.minute
|
16
|
+
# 3.days - 1.hour
|
17
|
+
#
|
18
|
+
# # good
|
19
|
+
# 1.minute.ago
|
20
|
+
# 2.days.from_now
|
21
|
+
class DurationArithmetic < Base
|
22
|
+
extend AutoCorrector
|
23
|
+
|
24
|
+
MSG = 'Do not add or subtract duration.'
|
25
|
+
|
26
|
+
RESTRICT_ON_SEND = %i[+ -].freeze
|
27
|
+
|
28
|
+
DURATIONS = Set[:second, :seconds, :minute, :minutes, :hour, :hours,
|
29
|
+
:day, :days, :week, :weeks, :fortnight, :fortnights]
|
30
|
+
|
31
|
+
# @!method duration_arithmetic_argument?(node)
|
32
|
+
# Match duration subtraction or addition with current time.
|
33
|
+
#
|
34
|
+
# @example source that matches
|
35
|
+
# Time.current - 1.hour
|
36
|
+
#
|
37
|
+
# @example source that matches
|
38
|
+
# ::Time.zone.now + 1.hour
|
39
|
+
#
|
40
|
+
# @param node [RuboCop::AST::Node]
|
41
|
+
# @yield operator and duration
|
42
|
+
def_node_matcher :duration_arithmetic_argument?, <<~PATTERN
|
43
|
+
(send #time_current? ${ :+ :- } $#duration?)
|
44
|
+
PATTERN
|
45
|
+
|
46
|
+
# @!method duration?(node)
|
47
|
+
# Match a literal Duration
|
48
|
+
#
|
49
|
+
# @example source that matches
|
50
|
+
# 1.hour
|
51
|
+
#
|
52
|
+
# @example source that matches
|
53
|
+
# 9.5.weeks
|
54
|
+
#
|
55
|
+
# @param node [RuboCop::AST::Node]
|
56
|
+
# @return [Boolean] true if matches
|
57
|
+
def_node_matcher :duration?, '(send { int float (send nil _) } DURATIONS)'
|
58
|
+
|
59
|
+
# @!method time_current?(node)
|
60
|
+
# Match Time.current
|
61
|
+
#
|
62
|
+
# @example source that matches
|
63
|
+
# Time.current
|
64
|
+
#
|
65
|
+
# @example source that matches
|
66
|
+
# ::Time.zone.now
|
67
|
+
#
|
68
|
+
# @param node [RuboCop::AST::Node]
|
69
|
+
# @return [Boolean] true if matches
|
70
|
+
def_node_matcher :time_current?, <<~PATTERN
|
71
|
+
{
|
72
|
+
(send (const _ :Time) :current)
|
73
|
+
(send (send (const _ :Time) :zone) :now)
|
74
|
+
}
|
75
|
+
PATTERN
|
76
|
+
|
77
|
+
def on_send(node)
|
78
|
+
duration_arithmetic_argument?(node) do |*operation|
|
79
|
+
add_offense(node) do |corrector|
|
80
|
+
corrector.replace(node.source_range, corrected_source(*operation))
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
def corrected_source(operator, duration)
|
88
|
+
if operator == :-
|
89
|
+
"#{duration.source}.ago"
|
90
|
+
else
|
91
|
+
"#{duration.source}.from_now"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -7,6 +7,10 @@ module RuboCop
|
|
7
7
|
# Use `find_by` instead of dynamic method.
|
8
8
|
# See. https://rails.rubystyle.guide#find_by
|
9
9
|
#
|
10
|
+
# @safety
|
11
|
+
# It is certainly unsafe when not configured properly, i.e. user-defined `find_by_xxx`
|
12
|
+
# method is not added to cop's `AllowedMethods`.
|
13
|
+
#
|
10
14
|
# @example
|
11
15
|
# # bad
|
12
16
|
# User.find_by_name(name)
|
@@ -43,9 +43,22 @@ module RuboCop
|
|
43
43
|
private
|
44
44
|
|
45
45
|
def ignored?(node)
|
46
|
+
return true if active_model_error_where?(node.receiver)
|
47
|
+
|
46
48
|
method_chain = node.each_node(:send).map(&:method_name)
|
49
|
+
|
47
50
|
(cop_config['IgnoredMethods'].map(&:to_sym) & method_chain).any?
|
48
51
|
end
|
52
|
+
|
53
|
+
def active_model_error_where?(node)
|
54
|
+
node.method?(:where) && active_model_error?(node.receiver)
|
55
|
+
end
|
56
|
+
|
57
|
+
def active_model_error?(node)
|
58
|
+
return false if node.nil?
|
59
|
+
|
60
|
+
node.send_type? && node.method?(:errors)
|
61
|
+
end
|
49
62
|
end
|
50
63
|
end
|
51
64
|
end
|
@@ -67,7 +67,7 @@ module RuboCop
|
|
67
67
|
private
|
68
68
|
|
69
69
|
def in_routing_block?(node)
|
70
|
-
!!node.each_ancestor(:block).detect { |block| ROUTING_METHODS.include?(block.
|
70
|
+
!!node.each_ancestor(:block).detect { |block| ROUTING_METHODS.include?(block.method_name) }
|
71
71
|
end
|
72
72
|
|
73
73
|
def needs_conversion?(data)
|
@@ -6,13 +6,14 @@ module RuboCop
|
|
6
6
|
# This cop checks that methods specified in the filter's `only` or
|
7
7
|
# `except` options are defined within the same class or module.
|
8
8
|
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
9
|
+
# @safety
|
10
|
+
# You can technically specify methods of superclass or methods added by
|
11
|
+
# mixins on the filter, but these can confuse developers. If you specify
|
12
|
+
# methods that are defined in other classes or modules, you should
|
13
|
+
# define the filter in that class or module.
|
14
|
+
#
|
15
|
+
# If you rely on behaviour defined in the superclass actions, you must
|
16
|
+
# remember to invoke `super` in the subclass actions.
|
16
17
|
#
|
17
18
|
# @example
|
18
19
|
# # bad
|
@@ -8,6 +8,10 @@ module RuboCop
|
|
8
8
|
# Without the `Mailer` suffix it isn't immediately apparent what's a mailer
|
9
9
|
# and which views are related to the mailer.
|
10
10
|
#
|
11
|
+
# @safety
|
12
|
+
# This cop's autocorrection is unsafe because renaming a constant is
|
13
|
+
# always an unsafe operation.
|
14
|
+
#
|
11
15
|
# @example
|
12
16
|
# # bad
|
13
17
|
# class User < ActionMailer::Base
|
@@ -6,8 +6,9 @@ module RuboCop
|
|
6
6
|
# This cop enforces the use of `collection.exclude?(obj)`
|
7
7
|
# over `!collection.include?(obj)`.
|
8
8
|
#
|
9
|
-
#
|
10
|
-
#
|
9
|
+
# @safety
|
10
|
+
# This cop is unsafe because false positive will occur for
|
11
|
+
# receiver objects that do not have an `exclude?` method. (e.g. `IPAddr`)
|
11
12
|
#
|
12
13
|
# @example
|
13
14
|
# # bad
|
@@ -5,6 +5,10 @@ module RuboCop
|
|
5
5
|
module Rails
|
6
6
|
# This cop checks for the use of output calls like puts and print
|
7
7
|
#
|
8
|
+
# @safety
|
9
|
+
# This cop's autocorrection is unsafe because depending on the Rails log level configuration,
|
10
|
+
# changing from `puts` to `Rails.logger.debug` could result in no output being shown.
|
11
|
+
#
|
8
12
|
# @example
|
9
13
|
# # bad
|
10
14
|
# puts 'A debug message'
|