brew vendor-gems: commit updates.

This commit is contained in:
BrewTestBot 2021-12-27 19:59:26 +00:00
parent b07ccd0f16
commit 0a6e953d77
No known key found for this signature in database
GPG Key ID: 82D7D104050B0F0F
114 changed files with 812 additions and 91 deletions

View File

@ -88,7 +88,7 @@ $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ruby-progressbar-1.11
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/unicode-display_width-2.1.0/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/unicode-display_width-2.1.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-1.24.0/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-1.24.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-performance-1.12.0/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-performance-1.12.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-rails-2.12.4/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-rails-2.13.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-rspec-2.7.0/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-rspec-2.7.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-sorbet-0.6.5/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-sorbet-0.6.5/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ruby-macho-2.5.1/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ruby-macho-2.5.1/lib"

View File

@ -180,6 +180,12 @@ Rails/BulkChangeTable:
Include: Include:
- db/migrate/*.rb - db/migrate/*.rb
Rails/CompactBlank:
Description: 'Checks if collection can be blank-compacted with `compact_blank`.'
Enabled: pending
Safe: false
VersionAdded: '2.13'
Rails/ContentTag: Rails/ContentTag:
Description: 'Use `tag.something` instead of `tag(:something)`.' Description: 'Use `tag.something` instead of `tag(:something)`.'
Reference: Reference:
@ -245,6 +251,12 @@ Rails/DelegateAllowBlank:
Enabled: true Enabled: true
VersionAdded: '0.44' VersionAdded: '0.44'
Rails/DurationArithmetic:
Description: 'Do not use duration as arithmetic operand with `Time.current`.'
StyleGuide: 'https://rails.rubystyle.guide#duration-arithmetic'
Enabled: pending
VersionAdded: '2.13'
Rails/DynamicFindBy: Rails/DynamicFindBy:
Description: 'Use `find_by` instead of dynamic `find_by_*`.' Description: 'Use `find_by` instead of dynamic `find_by_*`.'
StyleGuide: 'https://rails.rubystyle.guide#find_by' StyleGuide: 'https://rails.rubystyle.guide#find_by'
@ -612,6 +624,11 @@ Rails/RedundantForeignKey:
Enabled: true Enabled: true
VersionAdded: '2.6' VersionAdded: '2.6'
Rails/RedundantPresenceValidationOnBelongsTo:
Description: 'Checks for redundant presence validation on belongs_to association.'
Enabled: pending
VersionAdded: '2.13'
Rails/RedundantReceiverInWithOptions: Rails/RedundantReceiverInWithOptions:
Description: 'Checks for redundant receiver in `with_options`.' Description: 'Checks for redundant receiver in `with_options`.'
Enabled: true Enabled: true
@ -646,9 +663,9 @@ Rails/RefuteMethods:
Rails/RelativeDateConstant: Rails/RelativeDateConstant:
Description: 'Do not assign relative date to constants.' Description: 'Do not assign relative date to constants.'
Enabled: true Enabled: true
SafeAutoCorrect: false
VersionAdded: '0.48' VersionAdded: '0.48'
VersionChanged: '0.59' VersionChanged: '2.13'
AutoCorrect: false
Rails/RenderInline: Rails/RenderInline:
Description: 'Prefer using a template over inline rendering.' Description: 'Prefer using a template over inline rendering.'
@ -695,6 +712,11 @@ Rails/ReversibleMigrationMethodDefinition:
Include: Include:
- db/migrate/*.rb - db/migrate/*.rb
Rails/RootJoinChain:
Description: 'Use a single `#join` instead of chaining on `Rails.root` or `Rails.public_path`.'
Enabled: pending
VersionAdded: '2.13'
Rails/SafeNavigation: Rails/SafeNavigation:
Description: "Use Ruby's safe navigation operator (`&.`) instead of `try!`." Description: "Use Ruby's safe navigation operator (`&.`) instead of `try!`."
Enabled: true Enabled: true
@ -727,6 +749,13 @@ Rails/SaveBang:
AllowedReceivers: [] AllowedReceivers: []
SafeAutoCorrect: false SafeAutoCorrect: false
Rails/SchemaComment:
Description: >-
This cop enforces the use of the `comment` option when adding a new table or column
to the database during a migration.
Enabled: false
VersionAdded: '2.13'
Rails/ScopeArgs: Rails/ScopeArgs:
Description: 'Checks the arguments of ActiveRecord scopes.' Description: 'Checks the arguments of ActiveRecord scopes.'
Enabled: true Enabled: true
@ -789,9 +818,9 @@ Rails/TimeZone:
StyleGuide: 'https://rails.rubystyle.guide#time' StyleGuide: 'https://rails.rubystyle.guide#time'
Reference: 'http://danilenko.org/2012/7/6/rails_timezones' Reference: 'http://danilenko.org/2012/7/6/rails_timezones'
Enabled: true Enabled: true
Safe: false SafeAutoCorrect: false
VersionAdded: '0.30' VersionAdded: '0.30'
VersionChanged: '2.10' VersionChanged: '2.13'
# The value `strict` means that `Time` should be used with `zone`. # The value `strict` means that `Time` should be used with `zone`.
# The value `flexible` allows usage of `in_time_zone` instead of `zone`. # The value `flexible` allows usage of `in_time_zone` instead of `zone`.
EnforcedStyle: flexible EnforcedStyle: flexible
@ -814,13 +843,12 @@ Rails/UniqBeforePluck:
Description: 'Prefer the use of uniq or distinct before pluck.' Description: 'Prefer the use of uniq or distinct before pluck.'
Enabled: true Enabled: true
VersionAdded: '0.40' VersionAdded: '0.40'
VersionChanged: '2.8' VersionChanged: '2.13'
EnforcedStyle: conservative EnforcedStyle: conservative
SupportedStyles: SupportedStyles:
- conservative - conservative
- aggressive - aggressive
SafeAutoCorrect: false SafeAutoCorrect: false
AutoCorrect: false
Rails/UniqueValidationWithoutIndex: Rails/UniqueValidationWithoutIndex:
Description: 'Uniqueness validation should have a unique index on the database column.' Description: 'Uniqueness validation should have a unique index on the database column.'

View File

@ -0,0 +1,34 @@
# frozen_string_literal: true
module RuboCop
module Cop
# A mixin to extend cops for Active Record features
module ActiveRecordMigrationsHelper
extend NodePattern::Macros
RAILS_ABSTRACT_SCHEMA_DEFINITIONS = %i[
bigint binary boolean date datetime decimal float integer json string
text time timestamp virtual
].freeze
RAILS_ABSTRACT_SCHEMA_DEFINITIONS_HELPERS = %i[
column references belongs_to primary_key numeric
].freeze
POSTGRES_SCHEMA_DEFINITIONS = %i[
bigserial bit bit_varying cidr citext daterange hstore inet interval
int4range int8range jsonb ltree macaddr money numrange oid point line
lseg box path polygon circle serial tsrange tstzrange tsvector uuid xml
].freeze
MYSQL_SCHEMA_DEFINITIONS = %i[
blob tinyblob mediumblob longblob tinytext mediumtext longtext
unsigned_integer unsigned_bigint unsigned_float unsigned_decimal
].freeze
def_node_matcher :create_table_with_block?, <<~PATTERN
(block
(send nil? :create_table ...)
(args (arg _var))
_)
PATTERN
end
end
end

View File

@ -6,6 +6,10 @@ module RuboCop
# Checks that ActiveRecord aliases are not used. The direct method names # Checks that ActiveRecord aliases are not used. The direct method names
# are more clear and easier to read. # are more clear and easier to read.
# #
# @safety
# This cop is unsafe because custom `update_attributes` method call was changed to
# `update` but the method name remained same in the method definition.
#
# @example # @example
# #bad # #bad
# book.update_attributes!(author: 'Alice') # book.update_attributes!(author: 'Alice')

View File

@ -3,7 +3,11 @@
module RuboCop module RuboCop
module Cop module Cop
module Rails module Rails
# This cop checks that controllers subclass ApplicationController. # This cop checks that controllers subclass `ApplicationController`.
#
# @safety
# This cop's autocorrection is unsafe because it may let the logic from `ApplicationController`
# sneak into a controller that is not purposed to inherit logic common among other controllers.
# #
# @example # @example
# #

View File

@ -3,7 +3,11 @@
module RuboCop module RuboCop
module Cop module Cop
module Rails module Rails
# This cop checks that jobs subclass ApplicationJob with Rails 5.0. # This cop checks that jobs subclass `ApplicationJob` with Rails 5.0.
#
# @safety
# This cop's autocorrection is unsafe because it may let the logic from `ApplicationJob`
# sneak into a job that is not purposed to inherit logic common among other jobs.
# #
# @example # @example
# #

View File

@ -3,7 +3,11 @@
module RuboCop module RuboCop
module Cop module Cop
module Rails module Rails
# This cop checks that mailers subclass ApplicationMailer with Rails 5.0. # This cop checks that mailers subclass `ApplicationMailer` with Rails 5.0.
#
# @safety
# This cop's autocorrection is unsafe because it may let the logic from `ApplicationMailer`
# sneak into a mailer that is not purposed to inherit logic common among other mailers.
# #
# @example # @example
# #

View File

@ -3,7 +3,12 @@
module RuboCop module RuboCop
module Cop module Cop
module Rails module Rails
# This cop checks that models subclass ApplicationRecord with Rails 5.0. # This cop checks that models subclass `ApplicationRecord` with Rails 5.0.
#
# @safety
# This cop's autocorrection is unsafe because it may let the logic from `ApplicationRecord`
# sneak into an Active Record model that is not purposed to inherit logic common among other
# Active Record models.
# #
# @example # @example
# #

View File

@ -10,6 +10,12 @@ module RuboCop
# database to look for a column named <tt>`*`</tt> (or `"*"`) as opposed # database to look for a column named <tt>`*`</tt> (or `"*"`) as opposed
# to expanding the column list as one would likely expect. # to expanding the column list as one would likely expect.
# #
# @safety
# This cop's autocorrection is unsafe because it turns a quoted `*` into
# an SQL `*`, unquoted. `*` is a valid column name in certain databases
# supported by Rails, and even though it is usually a mistake,
# it might denote legitimate access to a column named `*`.
#
# @example # @example
# # bad # # bad
# MyTable.arel_table["*"] # MyTable.arel_table["*"]

View File

@ -6,15 +6,16 @@ module RuboCop
# This cop checks for code that can be written with simpler conditionals # This cop checks for code that can be written with simpler conditionals
# using `Object#blank?` defined by Active Support. # using `Object#blank?` defined by Active Support.
# #
# This cop is marked as unsafe auto-correction, because `' '.empty?` returns false,
# but `' '.blank?` returns true. Therefore, auto-correction is not compatible
# if the receiver is a non-empty blank string, tab, or newline meta characters.
#
# Interaction with `Style/UnlessElse`: # Interaction with `Style/UnlessElse`:
# The configuration of `NotPresent` will not produce an offense in the # The configuration of `NotPresent` will not produce an offense in the
# context of `unless else` if `Style/UnlessElse` is inabled. This is # context of `unless else` if `Style/UnlessElse` is inabled. This is
# to prevent interference between the auto-correction of the two cops. # to prevent interference between the auto-correction of the two cops.
# #
# @safety
# This cop is unsafe auto-correction, because `' '.empty?` returns false,
# but `' '.blank?` returns true. Therefore, auto-correction is not compatible
# if the receiver is a non-empty blank string, tab, or newline meta characters.
#
# @example NilOrEmpty: true (default) # @example NilOrEmpty: true (default)
# # Converts usages of `nil? || empty?` to `blank?` # # Converts usages of `nil? || empty?` to `blank?`
# #

View File

@ -0,0 +1,98 @@
# frozen_string_literal: true
module RuboCop
module Cop
module Rails
# Checks if collection can be blank-compacted with `compact_blank`.
#
# @safety
# It is unsafe by default because false positives may occur in the
# blank check of block arguments to the receiver object.
#
# For example, `[[1, 2], [3, nil]].reject { |first, second| second.blank? }` and
# `[[1, 2], [3, nil]].compact_blank` are not compatible. The same is true for `empty?`.
# This will work fine when the receiver is a hash object.
#
# @example
#
# # bad
# collection.reject(&:blank?)
# collection.reject(&:empty?)
# collection.reject { |_k, v| v.blank? }
# collection.reject { |_k, v| v.empty? }
#
# # good
# collection.compact_blank
#
# # bad
# collection.reject!(&:blank?)
# collection.reject!(&:empty?)
# collection.reject! { |_k, v| v.blank? }
# collection.reject! { |_k, v| v.empty? }
#
# # good
# collection.compact_blank!
#
class CompactBlank < Base
include RangeHelp
extend AutoCorrector
extend TargetRailsVersion
MSG = 'Use `%<preferred_method>s` instead.'
RESTRICT_ON_SEND = %i[reject reject!].freeze
minimum_target_rails_version 6.1
def_node_matcher :reject_with_block?, <<~PATTERN
(block
(send _ {:reject :reject!})
$(args ...)
(send
$(lvar _) {:blank? :empty?}))
PATTERN
def_node_matcher :reject_with_block_pass?, <<~PATTERN
(send _ {:reject :reject!}
(block_pass
(sym {:blank? :empty?})))
PATTERN
def on_send(node)
return unless bad_method?(node)
range = offense_range(node)
preferred_method = preferred_method(node)
add_offense(range, message: format(MSG, preferred_method: preferred_method)) do |corrector|
corrector.replace(range, preferred_method)
end
end
private
def bad_method?(node)
return true if reject_with_block_pass?(node)
if (arguments, receiver_in_block = reject_with_block?(node.parent))
return arguments.length == 1 || use_hash_value_block_argument?(arguments, receiver_in_block)
end
false
end
def use_hash_value_block_argument?(arguments, receiver_in_block)
arguments.length == 2 && arguments[1].source == receiver_in_block.source
end
def offense_range(node)
end_pos = node.parent&.block_type? ? node.parent.loc.expression.end_pos : node.loc.expression.end_pos
range_between(node.loc.selector.begin_pos, end_pos)
end
def preferred_method(node)
node.method?(:reject) ? 'compact_blank' : 'compact_blank!'
end
end
end
end
end

View File

@ -6,8 +6,8 @@ module RuboCop
# This cop checks legacy syntax usage of `tag` # This cop checks legacy syntax usage of `tag`
# #
# NOTE: Allow `tag` when the first argument is a variable because # NOTE: Allow `tag` when the first argument is a variable because
# `tag(name)` is simpler rather than `tag.public_send(name)`. # `tag(name)` is simpler rather than `tag.public_send(name)`.
# And this cop will be renamed to something like `LegacyTag` in the future. (e.g. RuboCop Rails 2.0) # And this cop will be renamed to something like `LegacyTag` in the future. (e.g. RuboCop Rails 2.0)
# #
# @example # @example
# # bad # # bad

View File

@ -41,16 +41,11 @@ module RuboCop
# t.datetime :updated_at, default: -> { 'CURRENT_TIMESTAMP' } # t.datetime :updated_at, default: -> { 'CURRENT_TIMESTAMP' }
# end # end
class CreateTableWithTimestamps < Base class CreateTableWithTimestamps < Base
include ActiveRecordMigrationsHelper
MSG = 'Add timestamps when creating a new table.' MSG = 'Add timestamps when creating a new table.'
RESTRICT_ON_SEND = %i[create_table].freeze RESTRICT_ON_SEND = %i[create_table].freeze
def_node_matcher :create_table_with_block?, <<~PATTERN
(block
(send nil? :create_table ...)
(args (arg _var))
_)
PATTERN
def_node_matcher :create_table_with_timestamps_proc?, <<~PATTERN def_node_matcher :create_table_with_timestamps_proc?, <<~PATTERN
(send nil? :create_table (sym _) ... (block-pass (sym :timestamps))) (send nil? :create_table (sym _) ... (block-pass (sym :timestamps)))
PATTERN PATTERN

View File

@ -0,0 +1,97 @@
# frozen_string_literal: true
module RuboCop
module Cop
module Rails
# This cop checks if a duration is added to or subtracted from `Time.current`.
#
# @example
# # bad
# Time.current - 1.minute
# Time.current + 2.days
#
# # good - using relative would make it harder to express and read
# Date.yesterday + 3.days
# created_at - 1.minute
# 3.days - 1.hour
#
# # good
# 1.minute.ago
# 2.days.from_now
class DurationArithmetic < Base
extend AutoCorrector
MSG = 'Do not add or subtract duration.'
RESTRICT_ON_SEND = %i[+ -].freeze
DURATIONS = Set[:second, :seconds, :minute, :minutes, :hour, :hours,
:day, :days, :week, :weeks, :fortnight, :fortnights]
# @!method duration_arithmetic_argument?(node)
# Match duration subtraction or addition with current time.
#
# @example source that matches
# Time.current - 1.hour
#
# @example source that matches
# ::Time.zone.now + 1.hour
#
# @param node [RuboCop::AST::Node]
# @yield operator and duration
def_node_matcher :duration_arithmetic_argument?, <<~PATTERN
(send #time_current? ${ :+ :- } $#duration?)
PATTERN
# @!method duration?(node)
# Match a literal Duration
#
# @example source that matches
# 1.hour
#
# @example source that matches
# 9.5.weeks
#
# @param node [RuboCop::AST::Node]
# @return [Boolean] true if matches
def_node_matcher :duration?, '(send { int float (send nil _) } DURATIONS)'
# @!method time_current?(node)
# Match Time.current
#
# @example source that matches
# Time.current
#
# @example source that matches
# ::Time.zone.now
#
# @param node [RuboCop::AST::Node]
# @return [Boolean] true if matches
def_node_matcher :time_current?, <<~PATTERN
{
(send (const _ :Time) :current)
(send (send (const _ :Time) :zone) :now)
}
PATTERN
def on_send(node)
duration_arithmetic_argument?(node) do |*operation|
add_offense(node) do |corrector|
corrector.replace(node.source_range, corrected_source(*operation))
end
end
end
private
def corrected_source(operator, duration)
if operator == :-
"#{duration.source}.ago"
else
"#{duration.source}.from_now"
end
end
end
end
end
end

View File

@ -7,6 +7,10 @@ module RuboCop
# Use `find_by` instead of dynamic method. # Use `find_by` instead of dynamic method.
# See. https://rails.rubystyle.guide#find_by # See. https://rails.rubystyle.guide#find_by
# #
# @safety
# It is certainly unsafe when not configured properly, i.e. user-defined `find_by_xxx`
# method is not added to cop's `AllowedMethods`.
#
# @example # @example
# # bad # # bad
# User.find_by_name(name) # User.find_by_name(name)

View File

@ -67,7 +67,7 @@ module RuboCop
private private
def in_routing_block?(node) def in_routing_block?(node)
!!node.each_ancestor(:block).detect { |block| ROUTING_METHODS.include?(block.send_node.method_name) } !!node.each_ancestor(:block).detect { |block| ROUTING_METHODS.include?(block.method_name) }
end end
def needs_conversion?(data) def needs_conversion?(data)

View File

@ -6,13 +6,14 @@ module RuboCop
# This cop checks that methods specified in the filter's `only` or # This cop checks that methods specified in the filter's `only` or
# `except` options are defined within the same class or module. # `except` options are defined within the same class or module.
# #
# You can technically specify methods of superclass or methods added by # @safety
# mixins on the filter, but these can confuse developers. If you specify # You can technically specify methods of superclass or methods added by
# methods that are defined in other classes or modules, you should # mixins on the filter, but these can confuse developers. If you specify
# define the filter in that class or module. # methods that are defined in other classes or modules, you should
# define the filter in that class or module.
# #
# If you rely on behaviour defined in the superclass actions, you must # If you rely on behaviour defined in the superclass actions, you must
# remember to invoke `super` in the subclass actions. # remember to invoke `super` in the subclass actions.
# #
# @example # @example
# # bad # # bad

View File

@ -8,6 +8,10 @@ module RuboCop
# Without the `Mailer` suffix it isn't immediately apparent what's a mailer # Without the `Mailer` suffix it isn't immediately apparent what's a mailer
# and which views are related to the mailer. # and which views are related to the mailer.
# #
# @safety
# This cop's autocorrection is unsafe because renaming a constant is
# always an unsafe operation.
#
# @example # @example
# # bad # # bad
# class User < ActionMailer::Base # class User < ActionMailer::Base

View File

@ -6,8 +6,9 @@ module RuboCop
# This cop enforces the use of `collection.exclude?(obj)` # This cop enforces the use of `collection.exclude?(obj)`
# over `!collection.include?(obj)`. # over `!collection.include?(obj)`.
# #
# It is marked as unsafe by default because false positive will occur for # @safety
# a receiver object that do not have `exclude?` method. (e.g. `IPAddr`) # This cop is unsafe because false positive will occur for
# receiver objects that do not have an `exclude?` method. (e.g. `IPAddr`)
# #
# @example # @example
# # bad # # bad

View File

@ -5,6 +5,10 @@ module RuboCop
module Rails module Rails
# This cop checks for the use of output calls like puts and print # This cop checks for the use of output calls like puts and print
# #
# @safety
# This cop's autocorrection is unsafe because depending on the Rails log level configuration,
# changing from `puts` to `Rails.logger.debug` could result in no output being shown.
#
# @example # @example
# # bad # # bad
# puts 'A debug message' # puts 'A debug message'

View File

@ -9,6 +9,13 @@ module RuboCop
# `pick` avoids. When called on an Active Record relation, `pick` adds a # `pick` avoids. When called on an Active Record relation, `pick` adds a
# limit to the query so that only one value is fetched from the database. # limit to the query so that only one value is fetched from the database.
# #
# @safety
# This cop is unsafe because `pluck` is defined on both `ActiveRecord::Relation` and `Enumerable`,
# whereas `pick` is only defined on `ActiveRecord::Relation` in Rails 6.0. This was addressed
# in Rails 6.1 via rails/rails#38760, at which point the cop is safe.
#
# See: https://github.com/rubocop/rubocop-rails/pull/249
#
# @example # @example
# # bad # # bad
# Model.pluck(:a).first # Model.pluck(:a).first

View File

@ -5,6 +5,9 @@ module RuboCop
module Rails module Rails
# This cop enforces the use of `ids` over `pluck(:id)` and `pluck(primary_key)`. # This cop enforces the use of `ids` over `pluck(:id)` and `pluck(primary_key)`.
# #
# @safety
# This cop is unsafe if the receiver object is not an Active Record object.
#
# @example # @example
# # bad # # bad
# User.pluck(:id) # User.pluck(:id)

View File

@ -9,14 +9,15 @@ module RuboCop
# Since `pluck` is an eager method and hits the database immediately, # Since `pluck` is an eager method and hits the database immediately,
# using `select` helps to avoid additional database queries. # using `select` helps to avoid additional database queries.
# #
# This cop has two different enforcement modes. When the EnforcedStyle # This cop has two different enforcement modes. When the `EnforcedStyle`
# is conservative (the default) then only calls to `pluck` on a constant # is `conservative` (the default) then only calls to `pluck` on a constant
# (i.e. a model class) in the `where` is used as offenses. # (i.e. a model class) in the `where` is used as offenses.
# #
# When the EnforcedStyle is aggressive then all calls to `pluck` in the # @safety
# `where` is used as offenses. This may lead to false positives # When the `EnforcedStyle` is `aggressive` then all calls to `pluck` in the
# as the cop cannot replace to `select` between calls to `pluck` on an # `where` is used as offenses. This may lead to false positives
# `ActiveRecord::Relation` instance vs a call to `pluck` on an `Array` instance. # as the cop cannot replace to `select` between calls to `pluck` on an
# `ActiveRecord::Relation` instance vs a call to `pluck` on an `Array` instance.
# #
# @example # @example
# # bad # # bad

View File

@ -14,6 +14,11 @@ module RuboCop
# * The task does not need application code. # * The task does not need application code.
# * The task invokes the `:environment` task. # * The task invokes the `:environment` task.
# #
# @safety
# Probably not a problem in most cases, but it is possible that calling `:environment` task
# will break a behavior. It's also slower. E.g. some task that only needs one gem to be
# loaded to run will run significantly faster without loading the whole application.
#
# @example # @example
# # bad # # bad
# task :foo do # task :foo do

View File

@ -0,0 +1,192 @@
# frozen_string_literal: true
module RuboCop
module Cop
module Rails
# Since Rails 5.0 the default for `belongs_to` is `optional: false`
# unless `config.active_record.belongs_to_required_by_default` is
# explicitly set to `false`. The presence validator is added
# automatically, and explicit presence validation is redundant.
#
# @example
# # bad
# belongs_to :user
# validates :user, presence: true
#
# # bad
# belongs_to :user
# validates :user_id, presence: true
#
# # bad
# belongs_to :author, foreign_key: :user_id
# validates :user_id, presence: true
#
# # good
# belongs_to :user
#
# # good
# belongs_to :author, foreign_key: :user_id
#
class RedundantPresenceValidationOnBelongsTo < Base
include RangeHelp
extend AutoCorrector
extend TargetRailsVersion
MSG = 'Remove explicit presence validation for `%<association>s`.'
RESTRICT_ON_SEND = %i[validates].freeze
minimum_target_rails_version 5.0
# @!method presence_validation?(node)
# Match a `validates` statement with a presence check
#
# @example source that matches - by association
# validates :user, presence: true
#
# @example source that matches - with presence options
# validates :user, presence: { message: 'duplicate' }
#
# @example source that matches - by a foreign key
# validates :user_id, presence: true
def_node_matcher :presence_validation?, <<~PATTERN
$(
send nil? :validates
(sym $_)
...
$(hash <$(pair (sym :presence) {true hash}) ...>)
)
PATTERN
# @!method optional_option?(node)
# Match a `belongs_to` association with an optional option in a hash
def_node_matcher :optional?, <<~PATTERN
(send nil? :belongs_to _ ... #optional_option?)
PATTERN
# @!method optional_option?(node)
# Match an optional option in a hash
def_node_matcher :optional_option?, <<~PATTERN
{
(hash <(pair (sym :optional) true) ...>) # optional: true
(hash <(pair (sym :required) false) ...>) # required: false
}
PATTERN
# @!method any_belongs_to?(node, association:)
# Match a class with `belongs_to` with no regard to `foreign_key` option
#
# @example source that matches
# belongs_to :user
#
# @example source that matches - regardless of `foreign_key`
# belongs_to :author, foreign_key: :user_id
#
# @param node [RuboCop::AST::Node]
# @param association [Symbol]
# @return [Array<RuboCop::AST::Node>, nil] matching node
def_node_matcher :any_belongs_to?, <<~PATTERN
(begin
<
$(send nil? :belongs_to (sym %association) ...)
...
>
)
PATTERN
# @!method belongs_to?(node, key:, fk:)
# Match a class with a matching association, either by name or an explicit
# `foreign_key` option
#
# @example source that matches - fk matches `foreign_key` option
# belongs_to :author, foreign_key: :user_id
#
# @example source that matches - key matches association name
# belongs_to :user
#
# @example source that does not match - explicit `foreign_key` does not match
# belongs_to :user, foreign_key: :account_id
#
# @param node [RuboCop::AST::Node]
# @param key [Symbol] e.g. `:user`
# @param fk [Symbol] e.g. `:user_id`
# @return [Array<RuboCop::AST::Node>] matching nodes
def_node_matcher :belongs_to?, <<~PATTERN
(begin
<
${
#belongs_to_without_fk?(%key) # belongs_to :user
#belongs_to_with_a_matching_fk?(%fk) # belongs_to :author, foreign_key: :user_id
}
...
>
)
PATTERN
# @!method belongs_to_without_fk?(node, fk)
# Match a matching `belongs_to` association, without an explicit `foreign_key` option
#
# @param node [RuboCop::AST::Node]
# @param key [Symbol] e.g. `:user`
# @return [Array<RuboCop::AST::Node>] matching nodes
def_node_matcher :belongs_to_without_fk?, <<~PATTERN
{
(send nil? :belongs_to (sym %1)) # belongs_to :user
(send nil? :belongs_to (sym %1) !hash) # belongs_to :user, -> { not_deleted }
(send nil? :belongs_to (sym %1) !(hash <(pair (sym :foreign_key) _) ...>))
}
PATTERN
# @!method belongs_to_with_a_matching_fk?(node, fk)
# Match a matching `belongs_to` association with a matching explicit `foreign_key` option
#
# @example source that matches
# belongs_to :author, foreign_key: :user_id
#
# @param node [RuboCop::AST::Node]
# @param fk [Symbol] e.g. `:user_id`
# @return [Array<RuboCop::AST::Node>] matching nodes
def_node_matcher :belongs_to_with_a_matching_fk?, <<~PATTERN
(send nil? :belongs_to ... (hash <(pair (sym :foreign_key) (sym %1)) ...>))
PATTERN
def on_send(node)
validation, key, options, presence = presence_validation?(node)
return unless validation
belongs_to = belongs_to_for(node.parent, key)
return unless belongs_to
return if optional?(belongs_to)
message = format(MSG, association: key.to_s)
add_offense(presence, message: message) do |corrector|
remove_presence_validation(corrector, node, options, presence)
end
end
private
def belongs_to_for(model_class_node, key)
if key.to_s.end_with?('_id')
normalized_key = key.to_s.delete_suffix('_id').to_sym
belongs_to?(model_class_node, key: normalized_key, fk: key)
else
any_belongs_to?(model_class_node, association: key)
end
end
def remove_presence_validation(corrector, node, options, presence)
if options.children.one?
corrector.remove(range_by_whole_lines(node.source_range, include_final_newline: true))
else
range = range_with_surrounding_comma(
range_with_surrounding_space(range: presence.source_range, side: :left),
:left
)
corrector.remove(range)
end
end
end
end
end
end

View File

@ -5,8 +5,10 @@ module RuboCop
module Rails module Rails
# This cop checks if the value of the option `class_name`, in # This cop checks if the value of the option `class_name`, in
# the definition of a reflection is a string. # the definition of a reflection is a string.
# It is marked as unsafe because it cannot be determined whether #
# constant or method return value specified to `class_name` is a string. # @safety
# This cop is unsafe because it cannot be determined whether
# constant or method return value specified to `class_name` is a string.
# #
# @example # @example
# # bad # # bad

View File

@ -6,6 +6,9 @@ module RuboCop
# This cop checks whether constant value isn't relative date. # This cop checks whether constant value isn't relative date.
# Because the relative date will be evaluated only once. # Because the relative date will be evaluated only once.
# #
# @safety
# This cop's autocorrection is unsafe because its dependence on the constant is not corrected.
#
# @example # @example
# # bad # # bad
# class SomeClass # class SomeClass

View File

@ -179,7 +179,7 @@ module RuboCop
MSG = '%<action>s is not reversible.' MSG = '%<action>s is not reversible.'
def_node_matcher :irreversible_schema_statement_call, <<~PATTERN def_node_matcher :irreversible_schema_statement_call, <<~PATTERN
(send nil? ${:execute :remove_belongs_to} ...) (send nil? ${:change_column :execute :remove_belongs_to :remove_reference} ...)
PATTERN PATTERN
def_node_matcher :drop_table_call, <<~PATTERN def_node_matcher :drop_table_call, <<~PATTERN

View File

@ -0,0 +1,72 @@
# frozen_string_literal: true
module RuboCop
module Cop
module Rails
# Use a single `#join` instead of chaining on `Rails.root` or `Rails.public_path`.
#
# @example
# # bad
# Rails.root.join('db').join('schema.rb')
# Rails.root.join('db').join(migrate).join('migration.rb')
# Rails.public_path.join('path').join('file.pdf')
# Rails.public_path.join('path').join(to).join('file.pdf')
#
# # good
# Rails.root.join('db', 'schema.rb')
# Rails.root.join('db', migrate, 'migration.rb')
# Rails.public_path.join('path', 'file.pdf')
# Rails.public_path.join('path', to, 'file.pdf')
#
class RootJoinChain < Base
extend AutoCorrector
include RangeHelp
MSG = 'Use `%<root>s.join(...)` instead of chaining `#join` calls.'
RESTRICT_ON_SEND = %i[join].to_set.freeze
# @!method rails_root?(node)
def_node_matcher :rails_root?, <<~PATTERN
(send (const {nil? cbase} :Rails) {:root :public_path})
PATTERN
# @!method join?(node)
def_node_matcher :join?, <<~PATTERN
(send _ :join $...)
PATTERN
def on_send(node)
evidence(node) do |rails_node, args|
add_offense(node, message: format(MSG, root: rails_node.source)) do |corrector|
range = range_between(rails_node.loc.selector.end_pos, node.loc.expression.end_pos)
replacement = ".join(#{args.map(&:source).join(', ')})"
corrector.replace(range, replacement)
end
end
end
private
def evidence(node)
# Are we at the *end* of the join chain?
return if join?(node.parent)
# Is there only one join?
return if rails_root?(node.receiver)
all_args = []
while (args = join?(node))
all_args = args + all_args
node = node.receiver
end
rails_root?(node) do
yield(node, all_args)
end
end
end
end
end
end

View File

@ -6,9 +6,18 @@ module RuboCop
# This cop checks to make sure safe navigation isn't used with `blank?` in # This cop checks to make sure safe navigation isn't used with `blank?` in
# a conditional. # a conditional.
# #
# While the safe navigation operator is generally a good idea, when # @safety
# checking `foo&.blank?` in a conditional, `foo` being `nil` will actually # While the safe navigation operator is generally a good idea, when
# do the opposite of what the author intends. # checking `foo&.blank?` in a conditional, `foo` being `nil` will actually
# do the opposite of what the author intends.
#
# For example:
#
# [source,ruby]
# ----
# foo&.blank? #=> nil
# foo.blank? #=> true
# ----
# #
# @example # @example
# # bad # # bad

View File

@ -25,6 +25,25 @@ module RuboCop
# You can permit receivers that are giving false positives with # You can permit receivers that are giving false positives with
# `AllowedReceivers: []` # `AllowedReceivers: []`
# #
# @safety
# This cop's autocorrection is unsafe because a custom `update` method call would be changed to `update!`,
# but the method name in the definition would be unchanged.
#
# [source,ruby]
# ----
# # Original code
# def update_attributes
# end
#
# update_attributes
#
# # After running rubocop --safe-auto-correct
# def update_attributes
# end
#
# update
# ----
#
# @example # @example
# #
# # bad # # bad

View File

@ -0,0 +1,104 @@
# frozen_string_literal: true
module RuboCop
module Cop
module Rails
# This cop enforces the use of the `comment` option when adding a new table or column
# to the database during a migration.
#
# @example
# # bad (no comment for a new column or table)
# add_column :table, :column, :integer
#
# create_table :table do |t|
# t.type :column
# end
#
# # good
# add_column :table, :column, :integer, comment: 'Number of offenses'
#
# create_table :table, comment: 'Table of offenses data' do |t|
# t.type :column, comment: 'Number of offenses'
# end
#
class SchemaComment < Base
include ActiveRecordMigrationsHelper
COLUMN_MSG = 'New database column without `comment`.'
TABLE_MSG = 'New database table without `comment`.'
RESTRICT_ON_SEND = %i[add_column create_table].freeze
CREATE_TABLE_COLUMN_METHODS = Set[
*(
RAILS_ABSTRACT_SCHEMA_DEFINITIONS |
RAILS_ABSTRACT_SCHEMA_DEFINITIONS_HELPERS |
POSTGRES_SCHEMA_DEFINITIONS |
MYSQL_SCHEMA_DEFINITIONS
)
].freeze
# @!method comment_present?(node)
def_node_matcher :comment_present?, <<~PATTERN
(hash <(pair {(sym :comment) (str "comment")} (_ [present?])) ...>)
PATTERN
# @!method add_column?(node)
def_node_matcher :add_column?, <<~PATTERN
(send nil? :add_column _table _column _type _?)
PATTERN
# @!method add_column_with_comment?(node)
def_node_matcher :add_column_with_comment?, <<~PATTERN
(send nil? :add_column _table _column _type #comment_present?)
PATTERN
# @!method create_table?(node)
def_node_matcher :create_table?, <<~PATTERN
(send nil? :create_table _table _?)
PATTERN
# @!method create_table?(node)
def_node_matcher :create_table_with_comment?, <<~PATTERN
(send nil? :create_table _table #comment_present? ...)
PATTERN
# @!method t_column?(node)
def_node_matcher :t_column?, <<~PATTERN
(send _var CREATE_TABLE_COLUMN_METHODS ...)
PATTERN
# @!method t_column_with_comment?(node)
def_node_matcher :t_column_with_comment?, <<~PATTERN
(send _var CREATE_TABLE_COLUMN_METHODS _column _type? #comment_present?)
PATTERN
def on_send(node)
if add_column_without_comment?(node)
add_offense(node, message: COLUMN_MSG)
elsif create_table?(node)
if create_table_without_comment?(node)
add_offense(node, message: TABLE_MSG)
elsif create_table_column_call_without_comment?(node)
add_offense(node.parent.body, message: COLUMN_MSG)
end
end
end
private
def add_column_without_comment?(node)
add_column?(node) && !add_column_with_comment?(node)
end
def create_table_without_comment?(node)
create_table?(node) && !create_table_with_comment?(node)
end
def create_table_column_call_without_comment?(node)
create_table_with_block?(node.parent) &&
t_column?(node.parent.body) &&
!t_column_with_comment?(node.parent.body)
end
end
end
end
end

View File

@ -5,8 +5,10 @@ module RuboCop
module Rails module Rails
# #
# Checks SQL heredocs to use `.squish`. # Checks SQL heredocs to use `.squish`.
# Some SQL syntax (e.g. PostgreSQL comments and functions) requires newlines #
# to be preserved in order to work, thus auto-correction for this cop is not safe. # @safety
# Some SQL syntax (e.g. PostgreSQL comments and functions) requires newlines
# to be preserved in order to work, thus auto-correction for this cop is not safe.
# #
# @example # @example
# # bad # # bad

View File

@ -14,6 +14,9 @@ module RuboCop
# When EnforcedStyle is 'flexible' then it's also allowed # When EnforcedStyle is 'flexible' then it's also allowed
# to use `Time#in_time_zone`. # to use `Time#in_time_zone`.
# #
# @safety
# This cop's autocorrection is unsafe because it may change handling time.
#
# @example # @example
# # bad # # bad
# Time.now # Time.now

Some files were not shown because too many files have changed in this diff Show More