rubocop-rails 2.12.3 → 2.13.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|