rubocop-rails 2.12.3 → 2.13.2
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.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/config/default.yml +40 -8
- data/lib/rubocop/cop/mixin/active_record_migrations_helper.rb +34 -0
- data/lib/rubocop/cop/mixin/migrations_helper.rb +26 -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 +99 -0
- data/lib/rubocop/cop/rails/content_tag.rb +2 -2
- data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +2 -7
- data/lib/rubocop/cop/rails/duration_arithmetic.rb +98 -0
- data/lib/rubocop/cop/rails/dynamic_find_by.rb +4 -0
- data/lib/rubocop/cop/rails/find_each.rb +2 -0
- data/lib/rubocop/cop/rails/http_positional_arguments.rb +1 -1
- data/lib/rubocop/cop/rails/index_by.rb +6 -6
- data/lib/rubocop/cop/rails/index_with.rb +6 -6
- data/lib/rubocop/cop/rails/inverse_of.rb +17 -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/read_write_attribute.rb +51 -14
- data/lib/rubocop/cop/rails/redundant_presence_validation_on_belongs_to.rb +257 -0
- data/lib/rubocop/cop/rails/reflection_class_name.rb +4 -2
- data/lib/rubocop/cop/rails/relative_date_constant.rb +3 -0
- data/lib/rubocop/cop/rails/reversible_migration.rb +5 -3
- data/lib/rubocop/cop/rails/reversible_migration_method_definition.rb +2 -10
- 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/unused_ignored_columns.rb +2 -0
- 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 +7 -0
- data/lib/rubocop/rails/version.rb +1 -1
- metadata +12 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 87ab88a596e8f8dbe2ef0ded9a93ae1ceba10572ad41fc6b4e1b0b684cf68110
|
4
|
+
data.tar.gz: 4bc8502424aa32efec36f06ca475b7a3918b160060f76aa65eba39bfa5a31947
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27016cd823ac6eb75ddb06f97c613fea178b29dc8cadac6289c803a9745ccbe2ffd7f7799c82b1a9ddd74f08ab162fcb50acf9a491a5841f1d09931eec8145fa
|
7
|
+
data.tar.gz: 95c826339433a0a87f296676216e62b493cdc4d5b67ac73c400659194d3a54e874554d0431c3cbea02316d4265cd870755320ed5f5fd6b42722fdd17feba041e
|
data/LICENSE.txt
CHANGED
data/config/default.yml
CHANGED
@@ -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:
|
@@ -245,6 +251,12 @@ Rails/DelegateAllowBlank:
|
|
245
251
|
Enabled: true
|
246
252
|
VersionAdded: '0.44'
|
247
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
|
+
|
248
260
|
Rails/DynamicFindBy:
|
249
261
|
Description: 'Use `find_by` instead of dynamic `find_by_*`.'
|
250
262
|
StyleGuide: 'https://rails.rubystyle.guide#find_by'
|
@@ -441,6 +453,7 @@ Rails/InverseOf:
|
|
441
453
|
Description: 'Checks for associations where the inverse cannot be determined automatically.'
|
442
454
|
Enabled: true
|
443
455
|
VersionAdded: '0.52'
|
456
|
+
IgnoreScopes: false
|
444
457
|
Include:
|
445
458
|
- app/models/**/*.rb
|
446
459
|
|
@@ -612,6 +625,12 @@ Rails/RedundantForeignKey:
|
|
612
625
|
Enabled: true
|
613
626
|
VersionAdded: '2.6'
|
614
627
|
|
628
|
+
Rails/RedundantPresenceValidationOnBelongsTo:
|
629
|
+
Description: 'Checks for redundant presence validation on belongs_to association.'
|
630
|
+
Enabled: pending
|
631
|
+
SafeAutoCorrect: false
|
632
|
+
VersionAdded: '2.13'
|
633
|
+
|
615
634
|
Rails/RedundantReceiverInWithOptions:
|
616
635
|
Description: 'Checks for redundant receiver in `with_options`.'
|
617
636
|
Enabled: true
|
@@ -646,9 +665,9 @@ Rails/RefuteMethods:
|
|
646
665
|
Rails/RelativeDateConstant:
|
647
666
|
Description: 'Do not assign relative date to constants.'
|
648
667
|
Enabled: true
|
668
|
+
SafeAutoCorrect: false
|
649
669
|
VersionAdded: '0.48'
|
650
|
-
VersionChanged: '
|
651
|
-
AutoCorrect: false
|
670
|
+
VersionChanged: '2.13'
|
652
671
|
|
653
672
|
Rails/RenderInline:
|
654
673
|
Description: 'Prefer using a template over inline rendering.'
|
@@ -685,15 +704,22 @@ Rails/ReversibleMigration:
|
|
685
704
|
Reference: 'https://api.rubyonrails.org/classes/ActiveRecord/Migration/CommandRecorder.html'
|
686
705
|
Enabled: true
|
687
706
|
VersionAdded: '0.47'
|
707
|
+
VersionChanged: '2.13'
|
688
708
|
Include:
|
689
|
-
- db
|
709
|
+
- db/**/*.rb
|
690
710
|
|
691
711
|
Rails/ReversibleMigrationMethodDefinition:
|
692
712
|
Description: 'Checks whether the migration implements either a `change` method or both an `up` and a `down` method.'
|
693
713
|
Enabled: false
|
694
714
|
VersionAdded: '2.10'
|
715
|
+
VersionChanged: '2.13'
|
695
716
|
Include:
|
696
|
-
- db
|
717
|
+
- db/**/*.rb
|
718
|
+
|
719
|
+
Rails/RootJoinChain:
|
720
|
+
Description: 'Use a single `#join` instead of chaining on `Rails.root` or `Rails.public_path`.'
|
721
|
+
Enabled: pending
|
722
|
+
VersionAdded: '2.13'
|
697
723
|
|
698
724
|
Rails/SafeNavigation:
|
699
725
|
Description: "Use Ruby's safe navigation operator (`&.`) instead of `try!`."
|
@@ -727,6 +753,13 @@ Rails/SaveBang:
|
|
727
753
|
AllowedReceivers: []
|
728
754
|
SafeAutoCorrect: false
|
729
755
|
|
756
|
+
Rails/SchemaComment:
|
757
|
+
Description: >-
|
758
|
+
This cop enforces the use of the `comment` option when adding a new table or column
|
759
|
+
to the database during a migration.
|
760
|
+
Enabled: false
|
761
|
+
VersionAdded: '2.13'
|
762
|
+
|
730
763
|
Rails/ScopeArgs:
|
731
764
|
Description: 'Checks the arguments of ActiveRecord scopes.'
|
732
765
|
Enabled: true
|
@@ -789,9 +822,9 @@ Rails/TimeZone:
|
|
789
822
|
StyleGuide: 'https://rails.rubystyle.guide#time'
|
790
823
|
Reference: 'http://danilenko.org/2012/7/6/rails_timezones'
|
791
824
|
Enabled: true
|
792
|
-
|
825
|
+
SafeAutoCorrect: false
|
793
826
|
VersionAdded: '0.30'
|
794
|
-
VersionChanged: '2.
|
827
|
+
VersionChanged: '2.13'
|
795
828
|
# The value `strict` means that `Time` should be used with `zone`.
|
796
829
|
# The value `flexible` allows usage of `in_time_zone` instead of `zone`.
|
797
830
|
EnforcedStyle: flexible
|
@@ -814,13 +847,12 @@ Rails/UniqBeforePluck:
|
|
814
847
|
Description: 'Prefer the use of uniq or distinct before pluck.'
|
815
848
|
Enabled: true
|
816
849
|
VersionAdded: '0.40'
|
817
|
-
VersionChanged: '2.
|
850
|
+
VersionChanged: '2.13'
|
818
851
|
EnforcedStyle: conservative
|
819
852
|
SupportedStyles:
|
820
853
|
- conservative
|
821
854
|
- aggressive
|
822
855
|
SafeAutoCorrect: false
|
823
|
-
AutoCorrect: false
|
824
856
|
|
825
857
|
Rails/UniqueValidationWithoutIndex:
|
826
858
|
Description: 'Uniqueness validation should have a unique index on the database column.'
|
@@ -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
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
# Common functionality for cops working with migrations
|
6
|
+
module MigrationsHelper
|
7
|
+
extend NodePattern::Macros
|
8
|
+
|
9
|
+
def_node_matcher :migration_class?, <<~PATTERN
|
10
|
+
(class
|
11
|
+
(const nil? _)
|
12
|
+
(send
|
13
|
+
(const (const {nil? cbase} :ActiveRecord) :Migration)
|
14
|
+
:[]
|
15
|
+
(float _))
|
16
|
+
_)
|
17
|
+
PATTERN
|
18
|
+
|
19
|
+
def in_migration?(node)
|
20
|
+
node.each_ancestor(:class).any? do |class_node|
|
21
|
+
migration_class?(class_node)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
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,99 @@
|
|
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 `blank?`.
|
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 { |_k, v| v.blank? }
|
21
|
+
#
|
22
|
+
# # good
|
23
|
+
# collection.compact_blank
|
24
|
+
#
|
25
|
+
# # bad
|
26
|
+
# collection.reject!(&:blank?)
|
27
|
+
# collection.reject! { |_k, v| v.blank? }
|
28
|
+
#
|
29
|
+
# # good
|
30
|
+
# collection.compact_blank!
|
31
|
+
#
|
32
|
+
class CompactBlank < Base
|
33
|
+
include RangeHelp
|
34
|
+
extend AutoCorrector
|
35
|
+
extend TargetRailsVersion
|
36
|
+
|
37
|
+
MSG = 'Use `%<preferred_method>s` instead.'
|
38
|
+
RESTRICT_ON_SEND = %i[reject reject!].freeze
|
39
|
+
|
40
|
+
minimum_target_rails_version 6.1
|
41
|
+
|
42
|
+
def_node_matcher :reject_with_block?, <<~PATTERN
|
43
|
+
(block
|
44
|
+
(send _ {:reject :reject!})
|
45
|
+
$(args ...)
|
46
|
+
(send
|
47
|
+
$(lvar _) :blank?))
|
48
|
+
PATTERN
|
49
|
+
|
50
|
+
def_node_matcher :reject_with_block_pass?, <<~PATTERN
|
51
|
+
(send _ {:reject :reject!}
|
52
|
+
(block_pass
|
53
|
+
(sym :blank?)))
|
54
|
+
PATTERN
|
55
|
+
|
56
|
+
def on_send(node)
|
57
|
+
return unless bad_method?(node)
|
58
|
+
|
59
|
+
range = offense_range(node)
|
60
|
+
preferred_method = preferred_method(node)
|
61
|
+
add_offense(range, message: format(MSG, preferred_method: preferred_method)) do |corrector|
|
62
|
+
corrector.replace(range, preferred_method)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def bad_method?(node)
|
69
|
+
return true if reject_with_block_pass?(node)
|
70
|
+
|
71
|
+
if (arguments, receiver_in_block = reject_with_block?(node.parent))
|
72
|
+
return use_single_value_block_argument?(arguments, receiver_in_block) ||
|
73
|
+
use_hash_value_block_argument?(arguments, receiver_in_block)
|
74
|
+
end
|
75
|
+
|
76
|
+
false
|
77
|
+
end
|
78
|
+
|
79
|
+
def use_single_value_block_argument?(arguments, receiver_in_block)
|
80
|
+
arguments.length == 1 && arguments[0].source == receiver_in_block.source
|
81
|
+
end
|
82
|
+
|
83
|
+
def use_hash_value_block_argument?(arguments, receiver_in_block)
|
84
|
+
arguments.length == 2 && arguments[1].source == receiver_in_block.source
|
85
|
+
end
|
86
|
+
|
87
|
+
def offense_range(node)
|
88
|
+
end_pos = node.parent&.block_type? ? node.parent.loc.expression.end_pos : node.loc.expression.end_pos
|
89
|
+
|
90
|
+
range_between(node.loc.selector.begin_pos, end_pos)
|
91
|
+
end
|
92
|
+
|
93
|
+
def preferred_method(node)
|
94
|
+
node.method?(:reject) ? 'compact_blank' : 'compact_blank!'
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
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
|
@@ -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,98 @@
|
|
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
|
+
:month, :months, :year, :years]
|
31
|
+
|
32
|
+
# @!method duration_arithmetic_argument?(node)
|
33
|
+
# Match duration subtraction or addition with current time.
|
34
|
+
#
|
35
|
+
# @example source that matches
|
36
|
+
# Time.current - 1.hour
|
37
|
+
#
|
38
|
+
# @example source that matches
|
39
|
+
# ::Time.zone.now + 1.hour
|
40
|
+
#
|
41
|
+
# @param node [RuboCop::AST::Node]
|
42
|
+
# @yield operator and duration
|
43
|
+
def_node_matcher :duration_arithmetic_argument?, <<~PATTERN
|
44
|
+
(send #time_current? ${ :+ :- } $#duration?)
|
45
|
+
PATTERN
|
46
|
+
|
47
|
+
# @!method duration?(node)
|
48
|
+
# Match a literal Duration
|
49
|
+
#
|
50
|
+
# @example source that matches
|
51
|
+
# 1.hour
|
52
|
+
#
|
53
|
+
# @example source that matches
|
54
|
+
# 9.5.weeks
|
55
|
+
#
|
56
|
+
# @param node [RuboCop::AST::Node]
|
57
|
+
# @return [Boolean] true if matches
|
58
|
+
def_node_matcher :duration?, '(send { int float (send nil _) } DURATIONS)'
|
59
|
+
|
60
|
+
# @!method time_current?(node)
|
61
|
+
# Match Time.current
|
62
|
+
#
|
63
|
+
# @example source that matches
|
64
|
+
# Time.current
|
65
|
+
#
|
66
|
+
# @example source that matches
|
67
|
+
# ::Time.zone.now
|
68
|
+
#
|
69
|
+
# @param node [RuboCop::AST::Node]
|
70
|
+
# @return [Boolean] true if matches
|
71
|
+
def_node_matcher :time_current?, <<~PATTERN
|
72
|
+
{
|
73
|
+
(send (const _ :Time) :current)
|
74
|
+
(send (send (const _ :Time) :zone) :now)
|
75
|
+
}
|
76
|
+
PATTERN
|
77
|
+
|
78
|
+
def on_send(node)
|
79
|
+
duration_arithmetic_argument?(node) do |*operation|
|
80
|
+
add_offense(node) do |corrector|
|
81
|
+
corrector.replace(node.source_range, corrected_source(*operation))
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
def corrected_source(operator, duration)
|
89
|
+
if operator == :-
|
90
|
+
"#{duration.source}.ago"
|
91
|
+
else
|
92
|
+
"#{duration.source}.from_now"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
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)
|
@@ -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)
|
@@ -23,22 +23,22 @@ module RuboCop
|
|
23
23
|
|
24
24
|
def_node_matcher :on_bad_each_with_object, <<~PATTERN
|
25
25
|
(block
|
26
|
-
(
|
26
|
+
(call _ :each_with_object (hash))
|
27
27
|
(args (arg $_el) (arg _memo))
|
28
|
-
(
|
28
|
+
(call (lvar _memo) :[]= $!`_memo (lvar _el)))
|
29
29
|
PATTERN
|
30
30
|
|
31
31
|
def_node_matcher :on_bad_to_h, <<~PATTERN
|
32
32
|
(block
|
33
|
-
(
|
33
|
+
(call _ :to_h)
|
34
34
|
(args (arg $_el))
|
35
35
|
(array $_ (lvar _el)))
|
36
36
|
PATTERN
|
37
37
|
|
38
38
|
def_node_matcher :on_bad_map_to_h, <<~PATTERN
|
39
|
-
(
|
39
|
+
(call
|
40
40
|
(block
|
41
|
-
(
|
41
|
+
(call _ {:map :collect})
|
42
42
|
(args (arg $_el))
|
43
43
|
(array $_ (lvar _el)))
|
44
44
|
:to_h)
|
@@ -49,7 +49,7 @@ module RuboCop
|
|
49
49
|
(const _ :Hash)
|
50
50
|
:[]
|
51
51
|
(block
|
52
|
-
(
|
52
|
+
(call _ {:map :collect})
|
53
53
|
(args (arg $_el))
|
54
54
|
(array $_ (lvar _el))))
|
55
55
|
PATTERN
|
@@ -26,22 +26,22 @@ module RuboCop
|
|
26
26
|
|
27
27
|
def_node_matcher :on_bad_each_with_object, <<~PATTERN
|
28
28
|
(block
|
29
|
-
(
|
29
|
+
(call _ :each_with_object (hash))
|
30
30
|
(args (arg $_el) (arg _memo))
|
31
|
-
(
|
31
|
+
(call (lvar _memo) :[]= (lvar _el) $!`_memo))
|
32
32
|
PATTERN
|
33
33
|
|
34
34
|
def_node_matcher :on_bad_to_h, <<~PATTERN
|
35
35
|
(block
|
36
|
-
(
|
36
|
+
(call _ :to_h)
|
37
37
|
(args (arg $_el))
|
38
38
|
(array (lvar _el) $_))
|
39
39
|
PATTERN
|
40
40
|
|
41
41
|
def_node_matcher :on_bad_map_to_h, <<~PATTERN
|
42
|
-
(
|
42
|
+
(call
|
43
43
|
(block
|
44
|
-
(
|
44
|
+
(call _ {:map :collect})
|
45
45
|
(args (arg $_el))
|
46
46
|
(array (lvar _el) $_))
|
47
47
|
:to_h)
|
@@ -52,7 +52,7 @@ module RuboCop
|
|
52
52
|
(const _ :Hash)
|
53
53
|
:[]
|
54
54
|
(block
|
55
|
-
(
|
55
|
+
(call _ {:map :collect})
|
56
56
|
(args (arg $_el))
|
57
57
|
(array (lvar _el) $_)))
|
58
58
|
PATTERN
|