Lint/AmbiguousAssignment
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
No |
1.7 |
- |
Checks for mistyped shorthand assignments.
Examples
# bad
x =- y
x =+ y
x =* y
x =! y
# good
x -= y # or x = -y
x += y # or x = +y
x *= y # or x = *y
x != y # or x = !y
Lint/AmbiguousBlockAssociation
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always |
0.48 |
1.13 |
Checks for ambiguous block association with method when param passed without parentheses.
This cop can customize allowed methods with AllowedMethods
.
By default, there are no methods to allowed.
Examples
# bad
some_method a { |val| puts val }
# good
# With parentheses, there's no ambiguity.
some_method(a { |val| puts val })
# or (different meaning)
some_method(a) { |val| puts val }
# good
# Operator methods require no disambiguation
foo == { |b| b.baz }
# good
# Lambda arguments require no disambiguation
foo = ->( ) { .baz }
AllowedMethods: [] (default)
# bad
expect { do_something }.to change { object.attribute }
AllowedMethods: [change]
# good
expect { do_something }.to change { object.attribute }
AllowedPatterns: [] (default)
# bad
expect { do_something }.to change { object.attribute }
AllowedPatterns: ['change']
# good
expect { do_something }.to change { object.attribute }
expect { do_something }.to not_change { object.attribute }
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
AllowedMethods |
|
Array |
AllowedPatterns |
|
Array |
Lint/AmbiguousOperator
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always |
0.17 |
0.83 |
Checks for ambiguous operators in the first argument of a method invocation without parentheses.
Examples
# bad
# The `*` is interpreted as a splat operator but it could possibly be
# a `*` method invocation (i.e. `do_something.*(some_array)`).
do_something *some_array
# good
# With parentheses, there's no ambiguity.
do_something(*some_array)
Lint/AmbiguousOperatorPrecedence
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
Always |
1.21 |
- |
Looks for expressions containing multiple binary operators
where precedence is ambiguous due to lack of parentheses. For example,
in 1 + 2 * 3
, the multiplication will happen before the addition, but
lexically it appears that the addition will happen first.
The cop does not consider unary operators (ie. !a
or -b
) or comparison
operators (ie. a =~ b
) because those are not ambiguous.
Note
|
Ranges are handled by Lint/AmbiguousRange .
|
Examples
# bad
a + b * c
a || b && c
a ** b + c
# good (different precedence)
a + (b * c)
a || (b && c)
(a ** b) + c
# good (same precedence)
a + b + c
a * b / c % d
Lint/AmbiguousRange
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
Always (Unsafe) |
1.19 |
- |
Checks for ambiguous ranges.
Ranges have quite low precedence, which leads to unexpected behavior when using a range with other operators. This cop avoids that by making ranges explicit by requiring parenthesis around complex range boundaries (anything that is not a literal: numerics, strings, symbols, etc.).
This cop can be configured with RequireParenthesesForMethodChains
in order to
specify whether method chains (including self.foo
) should be wrapped in parens
by this cop.
Note
|
Regardless of this configuration, if a method receiver is a basic literal
value, it will be wrapped in order to prevent the ambiguity of 1..2.to_a .
|
Safety
The cop autocorrects by wrapping the entire boundary in parentheses, which makes the outcome more explicit but is possible to not be the intention of the programmer. For this reason, this cop’s autocorrect is unsafe (it will not change the behavior of the code, but will not necessarily match the intent of the program).
Examples
# bad
x || 1..2
(x || 1..2)
1..2.to_a
# good, unambiguous
1..2
'a'..'z'
:..:baz
MyClass::MIN..MyClass::MAX
@min..@max
a..b
-a..b
# good, ambiguity removed
x || (1..2)
(x || 1)..2
(x || 1)..(y || 2)
(1..2).to_a
RequireParenthesesForMethodChains: false (default)
# good
a.foo..b.
(a.foo)..(b. )
RequireParenthesesForMethodChains: true
# bad
a.foo..b.
# good
(a.foo)..(b. )
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
RequireParenthesesForMethodChains |
|
Boolean |
Lint/AmbiguousRegexpLiteral
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always |
0.17 |
0.83 |
Checks for ambiguous regexp literals in the first argument of a method invocation without parentheses.
Examples
# bad
# This is interpreted as a method invocation with a regexp literal,
# but it could possibly be `/` method invocations.
# (i.e. `do_something./(pattern)./(i)`)
do_something /pattern/i
# good
# With parentheses, there's no ambiguity.
do_something(/pattern/i)
Lint/AssignmentInCondition
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always (Unsafe) |
0.9 |
1.45 |
Checks for assignments in the conditions of if/while/until.
AllowSafeAssignment
option for safe assignment.
By safe assignment we mean putting parentheses around
an assignment to indicate "I know I’m using an assignment
as a condition. It’s not a mistake."
Safety
This cop’s autocorrection is unsafe because it assumes that the author meant to use an assignment result as a condition.
Examples
# bad
if some_var = value
do_something
end
# good
if some_var == value
do_something
end
AllowSafeAssignment: true (default)
# good
if (some_var = value)
do_something
end
AllowSafeAssignment: false
# bad
if (some_var = value)
do_something
end
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
AllowSafeAssignment |
|
Boolean |
Lint/BigDecimalNew
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always |
0.53 |
- |
BigDecimal.new()
is deprecated since BigDecimal 1.3.3.
This cop identifies places where BigDecimal.new()
can be replaced by BigDecimal()
.
Examples
# bad
BigDecimal.new(123.456, 3)
# good
BigDecimal(123.456, 3)
Lint/BinaryOperatorWithIdenticalOperands
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
No |
No |
0.89 |
1.7 |
Checks for places where binary operator has identical operands.
It covers arithmetic operators: -
, /
, %
;
comparison operators: ==
, ===
, =~
, >
, >=
, <
, ⇐
;
bitwise operators: |
, ^
, &
;
boolean operators: &&
, ||
and "spaceship" operator - <⇒
.
Simple arithmetic operations are allowed by this cop: +
, ,
*
, <<
and >>
.
Although these can be rewritten in a different way, it should not be necessary to
do so. This does not include operations such as -
or /
where the result will
always be the same (x - x
will always be 0; x / x
will always be 1), and
thus are legitimate offenses.
Safety
This cop is unsafe as it does not consider side effects when calling methods and thus can generate false positives, for example:
if wr.take_char == '\0' && wr.take_char == '\0'
# ...
end
Examples
# bad
x / x
x.top >= x.top
if a.x != 0 && a.x != 0
do_something
end
def child?
left_child || left_child
end
# good
x + x
1 << 1
Lint/BooleanSymbol
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always (Unsafe) |
0.50 |
1.22 |
Checks for :true
and :false
symbols.
In most cases it would be a typo.
Safety
Autocorrection is unsafe for this cop because code relying
on :true
or :false
symbols will break when those are
changed to actual booleans.
Examples
# bad
:true
# good
true
# bad
:false
# good
false
Lint/CircularArgumentReference
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.33 |
- |
Checks for circular argument references in optional keyword arguments and optional ordinal arguments.
This cop mirrors a warning produced by MRI since 2.2.
Examples
# bad
def bake(pie: pie)
pie.heat_up
end
# good
def bake(pie:)
pie.refrigerate
end
# good
def bake(pie: self.pie)
pie.feed_to(user)
end
# bad
def cook(dry_ingredients = dry_ingredients)
dry_ingredients.reduce(&:+)
end
# good
def cook(dry_ingredients = self.dry_ingredients)
dry_ingredients.combine
end
Lint/ConstantDefinitionInBlock
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.91 |
1.3 |
Do not define constants within a block, since the block’s scope does not isolate or namespace the constant in any way.
If you are trying to define that constant once, define it outside of the block instead, or use a variable or method if defining the constant in the outer scope would be problematic.
For meta-programming, use const_set
.
Examples
# bad
task :lint do
FILES_TO_LINT = Dir['lib/*.rb']
end
# bad
describe 'making a request' do
class TestRequest; end
end
# bad
module M
extend ActiveSupport::Concern
included do
LIST = []
end
end
# good
task :lint do
files_to_lint = Dir['lib/*.rb']
end
# good
describe 'making a request' do
let(:test_request) { Class.new }
# see also `stub_const` for RSpec
end
# good
module M
extend ActiveSupport::Concern
included do
const_set(:LIST, [])
end
end
AllowedMethods: ['enums'] (default)
# good
# `enums` for Typed Enums via {T::Enum} in Sorbet.
# https://sorbet.org/docs/tenum
class TestEnum < T::Enum
enums do
Foo = new("foo")
end
end
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
AllowedMethods |
|
Array |
Lint/ConstantOverwrittenInRescue
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
Always |
1.31 |
- |
Checks for overwriting an exception with an exception result by use rescue ⇒
.
You intended to write as rescue StandardError
.
However, you have written rescue ⇒ StandardError
.
In that case, the result of rescue
will overwrite StandardError
.
Examples
# bad
begin
something
rescue => StandardError
end
# good
begin
something
rescue StandardError
end
Lint/ConstantResolution
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Disabled |
Yes |
No |
0.86 |
- |
Check that certain constants are fully qualified.
This is not enabled by default because it would mark a lot of offenses unnecessarily.
Generally, gems should fully qualify all constants to avoid conflicts with
the code that uses the gem. Enable this cop without using Only
/Ignore
Large projects will over time end up with one or two constant names that
are problematic because of a conflict with a library or just internally
using the same name a namespace and a class. To avoid too many unnecessary
offenses, Enable this cop with Only: [The, Constant, Names, Causing, Issues]
Note
|
Style/RedundantConstantBase cop is disabled if this cop is enabled to prevent
conflicting rules. Because it respects user configurations that want to enable
this cop which is disabled by default.
|
Examples
# By default checks every constant
# bad
User
# bad
User::Login
# good
::User
# good
::User::Login
Only: ['Login']
# Restrict this cop to only being concerned about certain constants
# bad
Login
# good
::Login
# good
User::Login
Ignore: ['Login']
# Restrict this cop not being concerned about certain constants
# bad
User
# good
::User::Login
# good
Login
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
Only |
|
Array |
Ignore |
|
Array |
Lint/Debugger
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.14 |
1.63 |
Checks for debug calls (such as debugger
or binding.pry
) that should
not be kept for production code.
The cop can be configured using DebuggerMethods
. By default, a number of gems
debug entrypoints are configured (Kernel
, Byebug
, Capybara
, debug.rb
,
Pry
, Rails
, RubyJard
, and WebConsole
). Additional methods can be added.
Specific default groups can be disabled if necessary:
Lint/Debugger:
DebuggerMethods:
WebConsole: ~
You can also add your own methods by adding a new category:
Lint/Debugger:
DebuggerMethods:
MyDebugger:
MyDebugger.debug_this
Some gems also ship files that will start a debugging session when required,
for example require 'debug/start'
from ruby/debug
. These requires can
be configured through DebuggerRequires
. It has the same structure as
DebuggerMethods
, which you can read about above.
Examples
# bad (ok during development)
# using pry
def some_method
binding.pry
do_something
end
# bad (ok during development)
# using byebug
def some_method
byebug
do_something
end
# good
def some_method
do_something
end
DebuggerMethods: [my_debugger]
# bad (ok during development)
def some_method
my_debugger
end
DebuggerRequires: [my_debugger/start]
# bad (ok during development)
require 'my_debugger/start'
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
DebuggerMethods |
|
|
DebuggerRequires |
|
Lint/DeprecatedClassMethods
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always |
0.19 |
- |
Checks for uses of the deprecated class method usages.
Examples
# bad
File.exists?(some_path)
Dir.exists?(some_path)
iterator?
attr :name, true
attr :name, false
ENV.freeze # Calling {Env.freeze} raises {TypeError} since Ruby 2.7.
ENV.clone
ENV.dup # Calling {Env.dup} raises {TypeError} since Ruby 3.1.
Socket.gethostbyname(host)
Socket.gethostbyaddr(host)
# good
File.exist?(some_path)
Dir.exist?(some_path)
block_given?
attr_accessor :name
attr_reader :name
ENV # {ENV.freeze} cannot prohibit changes to environment variables.
ENV.to_h
ENV.to_h # {ENV.dup} cannot dup {ENV}, use {ENV.to_h} to get a copy of {ENV} as a hash.
Addrinfo.getaddrinfo(nodename, service)
Addrinfo.tcp(host, port).getnameinfo
Lint/DeprecatedConstants
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
Always |
1.8 |
1.40 |
Checks for deprecated constants.
It has DeprecatedConstants
config. If there is an alternative method, you can set
alternative value as Alternative
. And you can set the deprecated version as
DeprecatedVersion
. These options can be omitted if they are not needed.
DeprecatedConstants:
'DEPRECATED_CONSTANT':
Alternative: 'alternative_value'
DeprecatedVersion: 'deprecated_version'
By default, NIL
, TRUE
, FALSE
, `Net::HTTPServerException, Random::DEFAULT
,
Struct::Group
, and Struct::Passwd
are configured.
Examples
# bad
NIL
TRUE
FALSE
Net::HTTPServerException
Random::DEFAULT # Return value of Ruby 2 is {Random} instance, Ruby 3.0 is {Random} class.
Struct::Group
Struct::Passwd
# good
nil
true
false
Net::HTTPClientException
Random.new # `::DEFAULT` has been deprecated in Ruby 3, `.new` is compatible with Ruby 2.
Etc::Group
Etc::Passwd
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
DeprecatedConstants |
|
Lint/DeprecatedOpenSSLConstant
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always |
0.84 |
- |
Algorithmic constants for OpenSSL::Cipher
and OpenSSL::Digest
deprecated since OpenSSL version 2.2.0. Prefer passing a string
instead.
Examples
# bad
OpenSSL::Cipher::AES.new(128, :GCM)
# good
OpenSSL::Cipher.new('aes-128-gcm')
# bad
OpenSSL::Digest::SHA256.new
# good
OpenSSL::Digest.new('SHA256')
# bad
OpenSSL::Digest::SHA256.digest('foo')
# good
OpenSSL::Digest.digest('SHA256', 'foo')
Lint/DisjunctiveAssignmentInConstructor
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
No |
Always (Unsafe) |
0.62 |
0.88 |
Checks constructors for disjunctive assignments (||=
) that should
be plain assignments.
So far, this cop is only concerned with disjunctive assignment of instance variables.
In ruby, an instance variable is nil until a value is assigned, so the disjunction is unnecessary. A plain assignment has the same effect.
Safety
This cop is unsafe because it can register a false positive when a method is redefined in a subclass that calls super. For example:
class Base
def initialize
@config ||= 'base'
end
end
class Derived < Base
def initialize
@config = 'derived'
super
end
end
Without the disjunctive assignment, Derived
will be unable to override
the value for @config
.
Examples
# bad
def initialize
@x ||= 1
end
# good
def initialize
@x = 1
end
Lint/DuplicateBranch
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
No |
1.3 |
1.7 |
Checks that there are no repeated bodies
within if/unless
, case-when
, case-in
and rescue
constructs.
With IgnoreLiteralBranches: true
, branches are not registered
as offenses if they return a basic literal value (string, symbol,
integer, float, rational, complex, true
, false
, or nil
), or
return an array, hash, regexp or range that only contains one of
the above basic literal values.
With IgnoreConstantBranches: true
, branches are not registered
as offenses if they return a constant value.
With IgnoreDuplicateElseBranch: true
, in conditionals with multiple branches,
duplicate 'else' branches are not registered as offenses.
Examples
# bad
if foo
do_foo
do_something_else
elsif
do_foo
do_something_else
end
# good
if foo ||
do_foo
do_something_else
end
# bad
case x
when foo
do_foo
when
do_foo
else
do_something_else
end
# good
case x
when foo,
do_foo
else
do_something_else
end
# bad
begin
do_something
rescue FooError
handle_error
rescue BarError
handle_error
end
# good
begin
do_something
rescue FooError, BarError
handle_error
end
IgnoreLiteralBranches: true
# good
case size
when "small" then 100
when "medium" then 250
when "large" then 1000
else 250
end
IgnoreConstantBranches: true
# good
case size
when "small" then SMALL_SIZE
when "medium" then MEDIUM_SIZE
when "large" then LARGE_SIZE
else MEDIUM_SIZE
end
IgnoreDuplicateElseBranch: true
# good
if foo
do_foo
elsif
else
do_foo
end
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
IgnoreLiteralBranches |
|
Boolean |
IgnoreConstantBranches |
|
Boolean |
IgnoreDuplicateElseBranch |
|
Boolean |
Lint/DuplicateCaseCondition
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.45 |
- |
Checks that there are no repeated conditions used in case 'when' expressions.
Examples
# bad
case x
when 'first'
do_something
when 'first'
do_something_else
end
# good
case x
when 'first'
do_something
when 'second'
do_something_else
end
Lint/DuplicateElsifCondition
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.88 |
- |
Checks that there are no repeated conditions used in if 'elsif'.
Examples
# bad
if x == 1
do_something
elsif x == 1
do_something_else
end
# good
if x == 1
do_something
elsif x == 2
do_something_else
end
Lint/DuplicateHashKey
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.34 |
0.77 |
Checks for duplicated keys in hash literals. This cop considers both primitive types and constants for the hash keys.
This cop mirrors a warning in Ruby 2.2.
Examples
# bad
hash = { food: 'apple', food: 'orange' }
# good
hash = { food: 'apple', other_food: 'orange' }
Lint/DuplicateMagicComment
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
Always |
1.37 |
- |
Checks for duplicated magic comments.
Examples
# bad
# encoding: ascii
# encoding: ascii
# good
# encoding: ascii
# bad
# frozen_string_literal: true
# frozen_string_literal: true
# good
# frozen_string_literal: true
Lint/DuplicateMatchPattern
Note
|
Required Ruby version: 2.7 |
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
No |
1.50 |
- |
Checks that there are no repeated patterns used in in
keywords.
Examples
# bad
case x
in 'first'
do_something
in 'first'
do_something_else
end
# good
case x
in 'first'
do_something
in 'second'
do_something_else
end
# bad - repeated alternate patterns with the same conditions don't depend on the order
case x
in foo |
first_method
in | foo
second_method
end
# good
case x
in foo |
first_method
in | baz
second_method
end
# bad - repeated hash patterns with the same conditions don't depend on the order
case x
in foo: a, bar: b
first_method
in bar: b, foo: a
second_method
end
# good
case x
in foo: a, bar: b
first_method
in bar: b, baz: c
second_method
end
# bad - repeated array patterns with elements in the same order
case x
in [foo, ]
first_method
in [foo, ]
second_method
end
# good
case x
in [foo, ]
first_method
in [, foo]
second_method
end
# bad - repeated the same patterns and guard conditions
case x
in foo if
first_method
in foo if
second_method
end
# good
case x
in foo if
first_method
in foo if baz
second_method
end
Lint/DuplicateMethods
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.29 |
- |
Checks for duplicated instance (or singleton) method definitions.
Examples
# bad
def foo
1
end
def foo
2
end
# bad
def foo
1
end
alias foo
# good
def foo
1
end
def
2
end
# good
def foo
1
end
alias foo
Lint/DuplicateRegexpCharacterClassElement
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
Always |
1.1 |
- |
Checks for duplicate elements in Regexp character classes.
Examples
# bad
r = /[xyx]/
# bad
r = /[0-9x0-9]/
# good
r = /[xy]/
# good
r = /[0-9x]/
Lint/DuplicateRequire
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always (Unsafe) |
0.90 |
1.28 |
Checks for duplicate require
s and require_relative
s.
Safety
This cop’s autocorrection is unsafe because it may break the dependency order
of require
.
Examples
# bad
require 'foo'
require 'bar'
require 'foo'
# good
require 'foo'
require 'bar'
# good
require 'foo'
require_relative 'foo'
Lint/DuplicateRescueException
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.89 |
- |
Checks that there are no repeated exceptions used in 'rescue' expressions.
Examples
# bad
begin
something
rescue FirstException
handle_exception
rescue FirstException
handle_other_exception
end
# good
begin
something
rescue FirstException
handle_exception
rescue SecondException
handle_other_exception
end
Lint/DuplicateSetElement
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
Always |
1.67 |
- |
Checks for duplicate literal, constant, or variable elements in Set.
Examples
# bad
Set[:foo, :, :foo]
# good
Set[:foo, : ]
# bad
Set.new([:foo, :, :foo])
# good
Set.new([:foo, : ])
# bad
[:foo, :, :foo].to_set
# good
[:foo, : ].to_set
Lint/EachWithObjectArgument
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.31 |
- |
Checks if each_with_object is called with an immutable argument. Since the argument is the object that the given block shall make calls on to build something based on the enumerable that each_with_object iterates over, an immutable argument makes no sense. It’s definitely a bug.
Examples
# bad
sum = numbers.each_with_object(0) { |e, a| a += e }
# good
num = 0
sum = numbers.each_with_object(num) { |e, a| a += e }
Lint/ElseLayout
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always |
0.17 |
1.2 |
Checks for odd else
block layout - like
having an expression on the same line as the else
keyword,
which is usually a mistake.
Its autocorrection tweaks layout to keep the syntax. So, this autocorrection
is compatible correction for bad case syntax, but if your code makes a mistake
with elsif
and else
, you will have to correct it manually.
Examples
# bad
if something
# ...
else do_this
do_that
end
# good
# This code is compatible with the bad case. It will be autocorrected like this.
if something
# ...
else
do_this
do_that
end
# This code is incompatible with the bad case.
# If `do_this` is a condition, `elsif` should be used instead of `else`.
if something
# ...
elsif do_this
do_that
end
Lint/EmptyBlock
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
No |
1.1 |
1.15 |
Checks for blocks without a body. Such empty blocks are typically an oversight or we should provide a comment to clarify what we’re aiming for.
Empty lambdas and procs are ignored by default.
Note
|
For backwards compatibility, the configuration that allows/disallows
empty lambdas and procs is called AllowEmptyLambdas , even though it also
applies to procs.
|
Examples
# bad
items.each { |item| }
# good
items.each { |item| puts item }
AllowComments: true (default)
# good
items.each do |item|
# TODO: implement later (inner comment)
end
items.each { |item| } # TODO: implement later (inline comment)
AllowComments: false
# bad
items.each do |item|
# TODO: implement later (inner comment)
end
items.each { |item| } # TODO: implement later (inline comment)
AllowEmptyLambdas: true (default)
# good
allow(subject).to receive(:callable).and_return(-> {})
placeholder = lambda do
end
(callable || placeholder).call
proc { }
Proc.new { }
AllowEmptyLambdas: false
# bad
allow(subject).to receive(:callable).and_return(-> {})
placeholder = lambda do
end
(callable || placeholder).call
proc { }
Proc.new { }
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
AllowComments |
|
Boolean |
AllowEmptyLambdas |
|
Boolean |
Lint/EmptyClass
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
No |
1.3 |
- |
Checks for classes and metaclasses without a body. Such empty classes and metaclasses are typically an oversight or we should provide a comment to be clearer what we’re aiming for.
Examples
# bad
class Foo
end
class Bar
class << self
end
end
class << obj
end
# good
class Foo
def do_something
# ... code
end
end
class Bar
class << self
attr_reader :
end
end
class << obj
attr_reader :
end
AllowComments: false (default)
# bad
class Foo
# TODO: implement later
end
class Bar
class << self
# TODO: implement later
end
end
class << obj
# TODO: implement later
end
AllowComments: true
# good
class Foo
# TODO: implement later
end
class Bar
class << self
# TODO: implement later
end
end
class << obj
# TODO: implement later
end
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
AllowComments |
|
Boolean |
Lint/EmptyConditionalBody
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Command-line only (Unsafe) |
0.89 |
1.61 |
Checks for the presence of if
, elsif
and unless
branches without a body.
Note
|
empty else branches are handled by Style/EmptyElse .
|
Safety
Autocorrection for this cop is not safe. The conditions for empty branches that the autocorrection removes may have side effects, or the logic in subsequent branches may change due to the removal of a previous condition.
Examples
# bad
if condition
end
# bad
unless condition
end
# bad
if condition
do_something
elsif other_condition
end
# good
if condition
do_something
end
# good
unless condition
do_something
end
# good
if condition
do_something
elsif other_condition
do_something_else
end
AllowComments: true (default)
# good
if condition
do_something
elsif other_condition
# noop
end
AllowComments: false
# bad
if condition
do_something
elsif other_condition
# noop
end
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
AllowComments |
|
Boolean |
Lint/EmptyEnsure
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Command-line only |
0.10 |
1.61 |
Checks for empty ensure
blocks.
Examples
# bad
def some_method
do_something
ensure
end
# bad
begin
do_something
ensure
end
# good
def some_method
do_something
ensure
do_something_else
end
# good
begin
do_something
ensure
do_something_else
end
Lint/EmptyExpression
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.45 |
- |
Checks for the presence of empty expressions.
Examples
# bad
foo = ()
if ()
end
# good
foo = (some_expression)
if (some_expression)
end
Lint/EmptyFile
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.90 |
- |
Enforces that Ruby source files are not empty.
Examples
# bad
# Empty file
# good
# File containing non commented source lines
AllowComments: true (default)
# good
# File consisting only of comments
AllowComments: false
# bad
# File consisting only of comments
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
AllowComments |
|
Boolean |
Lint/EmptyInPattern
Note
|
Required Ruby version: 2.7 |
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
No |
1.16 |
- |
Checks for the presence of in
pattern branches without a body.
Examples
# bad
case condition
in [a]
do_something
in [a, b]
end
# good
case condition
in [a]
do_something
in [a, b]
nil
end
AllowComments: true (default)
# good
case condition
in [a]
do_something
in [a, b]
# noop
end
AllowComments: false
# bad
case condition
in [a]
do_something
in [a, b]
# noop
end
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
AllowComments |
|
Boolean |
Lint/EmptyInterpolation
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Command-line only |
0.20 |
1.61 |
Checks for empty interpolation.
Examples
# bad
"result is #{}"
# good
"result is #{some_result}"
Lint/EmptyWhen
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.45 |
0.83 |
Checks for the presence of when
branches without a body.
Examples
# bad
case foo
when
do_something
when baz
end
# good
case condition
when foo
do_something
when
nil
end
AllowComments: true (default)
# good
case condition
when foo
do_something
when
# noop
end
AllowComments: false
# bad
case condition
when foo
do_something
when
# do nothing
end
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
AllowComments |
|
Boolean |
Lint/EnsureReturn
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.9 |
0.83 |
Checks for return
from an ensure
block.
return
from an ensure block is a dangerous code smell as it
will take precedence over any exception being raised,
and the exception will be silently thrown away as if it were rescued.
If you want to rescue some (or all) exceptions, best to do it explicitly
Examples
# bad
def foo
do_something
ensure
cleanup
return self
end
# good
def foo
do_something
self
ensure
cleanup
end
# good
def foo
begin
do_something
rescue SomeException
# Let's ignore this exception
end
self
ensure
cleanup
end
References
Lint/ErbNewArguments
Note
|
Required Ruby version: 2.6 |
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always |
0.56 |
- |
Emulates the following Ruby warnings in Ruby 2.6.
$ cat example.rb
ERB.new('hi', nil, '-', '@output_buffer')
$ ruby -rerb example.rb
example.rb:1: warning: Passing safe_level with the 2nd argument of ERB.new is
deprecated. Do not use it, and specify other arguments as keyword arguments.
example.rb:1: warning: Passing trim_mode with the 3rd argument of ERB.new is
deprecated. Use keyword argument like ERB.new(str, trim_mode:...) instead.
example.rb:1: warning: Passing eoutvar with the 4th argument of ERB.new is
deprecated. Use keyword argument like ERB.new(str, eoutvar: ...) instead.
Now non-keyword arguments other than first one are softly deprecated
and will be removed when Ruby 2.5 becomes EOL.
ERB.new
with non-keyword arguments is deprecated since ERB 2.2.0.
Use :trim_mode
and :eoutvar
keyword arguments to ERB.new
.
This cop identifies places where ERB.new(str, trim_mode, eoutvar)
can
be replaced by ERB.new(str, :trim_mode: trim_mode, eoutvar: eoutvar)
.
Examples
# Target codes supports Ruby 2.6 and higher only
# bad
ERB.new(str, nil, '-', '@output_buffer')
# good
ERB.new(str, trim_mode: '-', eoutvar: '@output_buffer')
# Target codes supports Ruby 2.5 and lower only
# good
ERB.new(str, nil, '-', '@output_buffer')
# Target codes supports Ruby 2.6, 2.5 and lower
# bad
ERB.new(str, nil, '-', '@output_buffer')
# good
# Ruby standard library style
# https://github.com/ruby/ruby/commit/3406c5d
if ERB.instance_method(:initialize).parameters.assoc(:key) # Ruby 2.6+
ERB.new(str, trim_mode: '-', eoutvar: '@output_buffer')
else
ERB.new(str, nil, '-', '@output_buffer')
end
# good
# Use {RUBY_VERSION} style
if RUBY_VERSION >= '2.6'
ERB.new(str, trim_mode: '-', eoutvar: '@output_buffer')
else
ERB.new(str, nil, '-', '@output_buffer')
end
Lint/FlipFlop
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.16 |
- |
Looks for uses of flip-flop operator based on the Ruby Style Guide.
Here is the history of flip-flops in Ruby. flip-flop operator is deprecated in Ruby 2.6.0 and the deprecation has been reverted by Ruby 2.7.0 and backported to Ruby 2.6. See: https://bugs.ruby-lang.org/issues/5400
Examples
# bad
(1..20).each do |x|
puts x if (x == 5) .. (x == 10)
end
# good
(1..20).each do |x|
puts x if (x >= 5) && (x <= 10)
end
References
Lint/FloatComparison
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.89 |
- |
Checks for the presence of precise comparison of floating point numbers.
Floating point values are inherently inaccurate, and comparing them for exact equality
is almost never the desired semantics. Comparison via the ==/!=
operators checks
floating-point value representation to be exactly the same, which is very unlikely
if you perform any arithmetic operations involving precision loss.
Examples
# bad
x == 0.1
x != 0.1
# good - using BigDecimal
x.to_d == 0.1.to_d
# good - comparing against zero
x == 0.0
x != 0.0
# good
(x - 0.1).abs < Float::EPSILON
# good
tolerance = 0.0001
(x - 0.1).abs < tolerance
# Or some other epsilon based type of comparison:
# https://www.embeddeduse.com/2019/08/26/qt-compare-two-floats/
References
Lint/FloatOutOfRange
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.36 |
- |
Identifies Float literals which are, like, really really really really really really really really big. Too big. No-one needs Floats that big. If you need a float that big, something is wrong with you.
Examples
# bad
float = 3.0e400
# good
float = 42.9
Lint/FormatParameterMismatch
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.33 |
- |
This lint sees if there is a mismatch between the number of expected fields for format/sprintf/#% and what is actually passed as arguments.
In addition it checks whether different formats are used in the same format string. Do not mix numbered, unnumbered, and named formats in the same format string.
Examples
# bad
format('A value: %s and another: %i', a_value)
# good
format('A value: %s and another: %i', a_value, another)
# bad
format('Unnumbered format: %s and numbered: %2$s', a_value, another)
# good
format('Numbered format: %1$s and numbered %2$s', a_value, another)
Lint/HashCompareByIdentity
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
No |
No |
0.93 |
- |
Prefer using Hash#compare_by_identity
rather than using object_id
for hash keys.
This cop looks for hashes being keyed by objects' object_id
, using
one of these methods: key?
, has_key?
, fetch
, []
and []=
.
Safety
This cop is unsafe. Although unlikely, the hash could store both object ids and other values that need be compared by value, and thus could be a false positive.
Furthermore, this cop cannot guarantee that the receiver of one of the
methods (key?
, etc.) is actually a hash.
Examples
# bad
hash = {}
hash[foo.object_id] = :
hash.key?(baz.object_id)
# good
hash = {}.compare_by_identity
hash[foo] = :
hash.key?(baz)
References
Lint/HeredocMethodCallPosition
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Disabled |
Yes |
Always |
0.68 |
- |
Checks for the ordering of a method call where the receiver of the call is a HEREDOC.
Examples
# bad
<<-SQL
bar
SQL
.strip_indent
<<-SQL
bar
SQL
.strip_indent
.trim
# good
<<~SQL
bar
SQL
<<~SQL.trim
bar
SQL
References
Lint/IdentityComparison
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always |
0.91 |
- |
Prefer equal?
over ==
when comparing object_id
.
Object#equal?
is provided to compare objects for identity, and in contrast
Object#==
is provided for the purpose of doing value comparison.
Examples
# bad
foo.object_id == .object_id
# good
foo.equal?( )
References
Lint/ImplicitStringConcatenation
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always |
0.36 |
- |
Checks for implicit string concatenation of string literals which are on the same line.
Examples
# bad
array = ['Item 1' 'Item 2']
# good
array = ['Item 1Item 2']
array = ['Item 1' + 'Item 2']
array = [
'Item 1' \
'Item 2'
]
Lint/IncompatibleIoSelectWithFiberScheduler
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
Always (Unsafe) |
1.21 |
1.24 |
Checks for IO.select
that is incompatible with Fiber Scheduler since Ruby 3.0.
When an array of IO objects waiting for an exception (the third argument of IO.select
)
is used as an argument, there is no alternative API, so offenses are not registered.
Safety
This cop’s autocorrection is unsafe because NoMethodError
occurs
if require 'io/wait'
is not called.
Examples
# bad
IO.select([io], [], [], timeout)
# good
io.wait_readable(timeout)
# bad
IO.select([], [io], [], timeout)
# good
io.wait_writable(timeout)
Lint/IneffectiveAccessModifier
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.36 |
- |
Checks for private
or protected
access modifiers which are
applied to a singleton method. These access modifiers do not make
singleton methods private/protected. private_class_method
can be
used for that.
Examples
# bad
class C
private
def self.method
puts 'hi'
end
end
# good
class C
def self.method
puts 'hi'
end
private_class_method :method
end
# good
class C
class << self
private
def method
puts 'hi'
end
end
end
Lint/InheritException
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always (Unsafe) |
0.41 |
1.26 |
Looks for error classes inheriting from Exception
.
It is configurable to suggest using either StandardError
(default) or
RuntimeError
instead.
Safety
This cop’s autocorrection is unsafe because rescue
that omit
exception class handle StandardError
and its subclasses,
but not Exception
and its subclasses.
Examples
EnforcedStyle: standard_error (default)
# bad
class C < Exception; end
C = Class.new(Exception)
# good
class C < StandardError; end
C = Class.new(StandardError)
EnforcedStyle: runtime_error
# bad
class C < Exception; end
C = Class.new(Exception)
# good
class C < RuntimeError; end
C = Class.new(RuntimeError)
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
EnforcedStyle |
|
|
Lint/InterpolationCheck
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always (Unsafe) |
0.50 |
1.40 |
Checks for interpolation in a single quoted string.
Safety
This cop’s autocorrection is unsafe because although it always replaces single quotes as
if it were miswritten double quotes, it is not always the case. For example,
'{foo} bar'
would be replaced by "{foo} bar"
, so the replaced code would evaluate
the expression foo
.
Examples
# bad
foo = 'something with #{interpolation} inside'
# good
foo = "something with #{interpolation} inside"
Lint/ItWithoutArgumentsInBlock
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
No |
1.59 |
- |
Emulates the following Ruby warning in Ruby 3.3.
$ ruby -e '0.times { it }'
-e:1: warning: `it` calls without arguments will refer to the first block param in Ruby 3.4;
use it() or self.it
it
calls without arguments will refer to the first block param in Ruby 3.4.
So use it()
or self.it
to ensure compatibility.
Examples
# bad
do_something { it }
# good
do_something { it() }
do_something { self.it }
References
Lint/LambdaWithoutLiteralBlock
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
Always |
1.8 |
- |
Checks uses of lambda without a literal block. It emulates the following warning in Ruby 3.0:
$ ruby -vwe 'lambda(&proc {})'
ruby 3.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin19]
-e:1: warning: lambda without a literal block is deprecated; use the proc without
lambda instead
This way, proc object is never converted to lambda. Autocorrection replaces with compatible proc argument.
Examples
# bad
lambda(&proc { do_something })
lambda(&Proc.new { do_something })
# good
proc { do_something }
Proc.new { do_something }
lambda { do_something } # If you use lambda.
Lint/LiteralAsCondition
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.51 |
- |
Checks for literals used as the conditions or as operands in and/or expressions serving as the conditions of if/while/until/case-when/case-in.
Note
|
Literals in case-in condition where the match variable is used in
in are accepted as a pattern matching.
|
Examples
# bad
if 20
do_something
end
# bad
if some_var && true
do_something
end
# good
if some_var && some_condition
do_something
end
# good
# When using a boolean value for an infinite loop.
while true
break if condition
end
Lint/LiteralAssignmentInCondition
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
No |
1.58 |
- |
Checks for literal assignments in the conditions of if
, while
, and until
.
It emulates the following Ruby warning:
$ ruby -we 'if x = true; end'
-e:1: warning: found `= literal' in conditional, should be ==
As a lint cop, it cannot be determined if ==
is appropriate as intended,
therefore this cop does not provide autocorrection.
Examples
# bad
if x = 42
do_something
end
# good
if x == 42
do_something
end
# good
if x = y
do_something
end
Lint/LiteralInInterpolation
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always |
0.19 |
0.32 |
Checks for interpolated literals.
Examples
# bad
"result is #{10}"
# good
"result is 10"
Lint/Loop
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
No |
Always (Unsafe) |
0.9 |
1.3 |
Checks for uses of begin…end while/until something
.
Safety
The cop is unsafe because behavior can change in some cases, including
if a local variable inside the loop body is accessed outside of it, or if the
loop body raises a StopIteration
exception (which Kernel#loop
rescues).
Examples
# bad
# using while
begin
do_something
end while some_condition
# good
# while replacement
loop do
do_something
break unless some_condition
end
# bad
# using until
begin
do_something
end until some_condition
# good
# until replacement
loop do
do_something
break if some_condition
end
References
Lint/MissingCopEnableDirective
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.52 |
- |
Checks that there is an # rubocop:enable …
statement
after a # rubocop:disable …
statement. This will prevent leaving
cop disables on wide ranges of code, that latter contributors to
a file wouldn’t be aware of.
Examples
# Lint/MissingCopEnableDirective:
# MaximumRangeSize: .inf
# good
# rubocop:disable Layout/SpaceAroundOperators
x= 0
# rubocop:enable Layout/SpaceAroundOperators
# y = 1
# EOF
# bad
# rubocop:disable Layout/SpaceAroundOperators
x= 0
# EOF
# Lint/MissingCopEnableDirective:
# MaximumRangeSize: 2
# good
# rubocop:disable Layout/SpaceAroundOperators
x= 0
# With the previous, there are 2 lines on which cop is disabled.
# rubocop:enable Layout/SpaceAroundOperators
# bad
# rubocop:disable Layout/SpaceAroundOperators
x= 0
x += 1
# Including this, that's 3 lines on which the cop is disabled.
# rubocop:enable Layout/SpaceAroundOperators
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
MaximumRangeSize |
|
Float |
Lint/MissingSuper
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.89 |
1.4 |
Checks for the presence of constructors and lifecycle callbacks
without calls to super
.
This cop does not consider method_missing
(and respond_to_missing?
)
because in some cases it makes sense to overtake what is considered a
missing method. In other cases, the theoretical ideal handling could be
challenging or verbose for no actual gain.
Autocorrection is not supported because the position of super
cannot be
determined automatically.
Object
and BasicObject
are allowed by this cop because of their
stateless nature. However, sometimes you might want to allow other parent
classes from this cop, for example in the case of an abstract class that is
not meant to be called with super
. In those cases, you can use the
AllowedParentClasses
option to specify which classes should be allowed
in addition to Object
and BasicObject
.
Examples
# bad
class Employee < Person
def initialize(name, salary)
@salary = salary
end
end
# good
class Employee < Person
def initialize(name, salary)
super(name)
@salary = salary
end
end
# bad
Employee = Class.new(Person) do
def initialize(name, salary)
@salary = salary
end
end
# good
Employee = Class.new(Person) do
def initialize(name, salary)
super(name)
@salary = salary
end
end
# bad
class Parent
def self.inherited(base)
do_something
end
end
# good
class Parent
def self.inherited(base)
super
do_something
end
end
# good
class ClassWithNoParent
def initialize
do_something
end
end
AllowedParentClasses: [MyAbstractClass]
# good
class MyConcreteClass < MyAbstractClass
def initialize
do_something
end
end
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
AllowedParentClasses |
|
Array |
Lint/MixedCaseRange
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
Always (Unsafe) |
1.53 |
- |
Checks for mixed-case character ranges since they include likely unintended characters.
Offenses are registered for regexp character classes like /[A-z]/
as well as range objects like ('A'..'z')
.
Note
|
Range objects cannot be autocorrected. |
Safety
The cop autocorrects regexp character classes
by replacing one character range with two: A-z
becomes A-Za-z
.
In most cases this is probably what was originally intended
but it changes the regexp to no longer match symbols it used to include.
For this reason, this cop’s autocorrect is unsafe (it will
change the behavior of the code).
Examples
# bad
r = /[A-z]/
# good
r = /[A-Za-z]/
Lint/MixedRegexpCaptureTypes
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.85 |
- |
Do not mix named captures and numbered captures in a Regexp literal because numbered capture is ignored if they’re mixed. Replace numbered captures with non-capturing groupings or named captures.
Examples
# bad
/(?<foo>FOO)(BAR)/
# good
/(?<foo>FOO)(?<bar>BAR)/
# good
/(?<foo>FOO)(?:BAR)/
# good
/(FOO)(BAR)/
Lint/MultipleComparison
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always |
0.47 |
1.1 |
In math and Python, we can use x < y < z
style comparison to compare
multiple value. However, we can’t use the comparison in Ruby. However,
the comparison is not syntax error. This cop checks the bad usage of
comparison operators.
Examples
# bad
x < y < z
10 <= x <= 20
# good
x < y && y < z
10 <= x && x <= 20
Lint/NestedMethodDefinition
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.32 |
- |
Checks for nested method definitions.
Examples
# bad
# `bar` definition actually produces methods in the same scope
# as the outer `foo` method. Furthermore, the `bar` method
# will be redefined every time `foo` is invoked.
def foo
def
end
end
# good
def foo
= -> { puts 'hello' }
.call
end
# good
# `class_eval`, `instance_eval`, `module_eval`, `class_exec`, `instance_exec`, and
# `module_exec` blocks are allowed by default.
def foo
self.class.class_eval do
def
end
end
end
def foo
self.class.module_exec do
def
end
end
end
# good
def foo
class << self
def
end
end
end
AllowedMethods: [] (default)
# bad
def do_something
has_many :articles do
def find_or_create_by_name(name)
end
end
end
AllowedMethods: ['has_many']
# bad
def do_something
has_many :articles do
def find_or_create_by_name(name)
end
end
end
AllowedPatterns: [] (default)
# bad
def foo(obj)
obj.do_baz do
def
end
end
end
AllowedPatterns: ['baz']
# good
def foo(obj)
obj.do_baz do
def
end
end
end
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
AllowedMethods |
|
Array |
AllowedPatterns |
|
Array |
References
Lint/NestedPercentLiteral
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.52 |
- |
Checks for nested percent literals.
Examples
# bad
# The percent literal for nested_attributes is parsed as four tokens,
# yielding the array [:name, :content, :"%i[incorrectly", :"nested]"].
attributes = {
valid_attributes: %i[name content],
nested_attributes: %i[name content %i[incorrectly nested]]
}
# good
# Neither is incompatible with the bad case, but probably the intended code.
attributes = {
valid_attributes: %i[name content],
nested_attributes: [:name, :content, %i[incorrectly nested]]
}
attributes = {
valid_attributes: %i[name content],
nested_attributes: [:name, :content, [:incorrectly, :nested]]
}
Lint/NextWithoutAccumulator
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.36 |
- |
Don’t omit the accumulator when calling next
in a reduce
block.
Examples
# bad
result = (1..4).reduce(0) do |acc, i|
next if i.odd?
acc + i
end
# good
result = (1..4).reduce(0) do |acc, i|
next acc if i.odd?
acc + i
end
Lint/NoReturnInBeginEndBlocks
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
No |
1.2 |
- |
Checks for the presence of a return
inside a begin..end
block
in assignment contexts.
In this situation, the return
will result in an exit from the current
method, possibly leading to unexpected behavior.
Examples
# bad
@some_variable ||= begin
return some_value if some_condition_is_met
do_something
end
# good
@some_variable ||= begin
if some_condition_is_met
some_value
else
do_something
end
end
# good
some_variable = if some_condition_is_met
return if another_condition_is_met
some_value
else
do_something
end
Lint/NonAtomicFileOperation
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
Always (Unsafe) |
1.31 |
- |
Checks for non-atomic file operation. And then replace it with a nearly equivalent and atomic method.
These can cause problems that are difficult to reproduce, especially in cases of frequent file operations in parallel, such as test runs with parallel_rspec.
For examples: creating a directory if there is none, has the following problems
An exception occurs when the directory didn’t exist at the time of exist?
,
but someone else created it before mkdir
was executed.
Subsequent processes are executed without the directory that should be there
when the directory existed at the time of exist?
,
but someone else deleted it shortly afterwards.
Safety
This cop is unsafe, because autocorrection change to atomic processing. The atomic processing of the replacement destination is not guaranteed to be strictly equivalent to that before the replacement.
Examples
# bad - race condition with another process may result in an error in `mkdir`
unless Dir.exist?(path)
FileUtils.mkdir(path)
end
# good - atomic and idempotent creation
FileUtils.mkdir_p(path)
# bad - race condition with another process may result in an error in `remove`
if File.exist?(path)
FileUtils.remove(path)
end
# good - atomic and idempotent removal
FileUtils.rm_f(path)
Lint/NonDeterministicRequireOrder
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
No |
Always (Unsafe) |
0.78 |
- |
Dir[…]
and Dir.glob(…)
do not make any guarantees about
the order in which files are returned. The final order is
determined by the operating system and file system.
This means that using them in cases where the order matters,
such as requiring files, can lead to intermittent failures
that are hard to debug. To ensure this doesn’t happen,
always sort the list.
Dir.glob
and Dir[]
sort globbed results by default in Ruby 3.0.
So all bad cases are acceptable when Ruby 3.0 or higher are used.
Note
|
This cop will be deprecated and removed when supporting only Ruby 3.0 and higher. |
Safety
This cop is unsafe in the case where sorting files changes existing expected behavior.
Examples
# bad
Dir["./lib/**/*.rb"].each do |file|
require file
end
# good
Dir["./lib/**/*.rb"].sort.each do |file|
require file
end
# bad
Dir.glob(Rails.root.join(__dir__, 'test', '*.rb')) do |file|
require file
end
# good
Dir.glob(Rails.root.join(__dir__, 'test', '*.rb')).sort.each do |file|
require file
end
# bad
Dir['./lib/**/*.rb'].each(&method(:require))
# good
Dir['./lib/**/*.rb'].sort.each(&method(:require))
# bad
Dir.glob(Rails.root.join('test', '*.rb'), &method(:require))
# good
Dir.glob(Rails.root.join('test', '*.rb')).sort.each(&method(:require))
# good - Respect intent if `sort` keyword option is specified in Ruby 3.0 or higher.
Dir.glob(Rails.root.join(__dir__, 'test', '*.rb'), sort: false).each(&method(:require))
Lint/NonLocalExitFromIterator
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.30 |
- |
Checks for non-local exits from iterators without a return value. It registers an offense under these conditions:
-
No value is returned,
-
the block is preceded by a method chain,
-
the block has arguments,
-
the method which receives the block is not
define_method
ordefine_singleton_method
, -
the return is not contained in an inner scope, e.g. a lambda or a method definition.
Examples
class ItemApi
rescue_from ValidationError do |e| # non-iteration block with arg
return { message: 'validation error' } unless e.errors # allowed
error_array = e.errors.map do |error| # block with method chain
return if error.suppress? # warned
return "#{error.param}: invalid" unless error. # allowed
"#{error.param}: #{error.}"
end
{ message: 'validation error', errors: error_array }
end
def update_items
transaction do # block without arguments
return unless update_necessary? # allowed
find_each do |item| # block without method chain
return if item.stock == 0 # false-negative...
item.update!(foobar: true)
end
end
end
end
Lint/NumberConversion
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Disabled |
Yes |
Always (Unsafe) |
0.53 |
1.1 |
Warns the usage of unsafe number conversions. Unsafe number conversion can cause unexpected error if auto type conversion fails. Cop prefer parsing with number class instead.
Conversion with Integer
, Float
, etc. will raise an ArgumentError
if given input that is not numeric (eg. an empty string), whereas
to_i
, etc. will try to convert regardless of input (''.to_i ⇒ 0
).
As such, this cop is disabled by default because it’s not necessarily
always correct to raise if a value is not numeric.
Note
|
Some values cannot be converted properly using one of the Kernel
method (for instance, Time and DateTime values are allowed by this
cop by default). Similarly, Rails' duration methods do not work well
with Integer() and can be allowed with AllowedMethods . By default,
there are no methods to allowed.
|
Safety
Autocorrection is unsafe because it is not guaranteed that the
replacement Kernel
methods are able to properly handle the
input if it is not a standard class.
Examples
# bad
'10'.to_i
'10.2'.to_f
'10'.to_c
'1/3'.to_r
['1', '2', '3'].map(&:to_i)
foo.try(:to_f)
.send(:to_c)
# good
Integer('10', 10)
Float('10.2')
Complex('10')
Rational('1/3')
['1', '2', '3'].map { |i| Integer(i, 10) }
foo.try { |i| Float(i) }
.send { |i| Complex(i) }
AllowedMethods: [] (default)
# bad
10.minutes.to_i
AllowedMethods: [minutes]
# good
10.minutes.to_i
AllowedPatterns: [] (default)
# bad
10.minutes.to_i
AllowedPatterns: ['min*']
# good
10.minutes.to_i
IgnoredClasses: [Time, DateTime] (default)
# good
Time.now.to_datetime.to_i
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
AllowedMethods |
|
Array |
AllowedPatterns |
|
Array |
IgnoredClasses |
|
Array |
Lint/NumberedParameterAssignment
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
No |
1.9 |
- |
Checks for uses of numbered parameter assignment. It emulates the following warning in Ruby 2.7:
$ ruby -ve '_1 = :value'
ruby 2.7p137 (2020-10-01 revision 5445e04352) [x86_64-darwin19]
-e:1: warning: `_1' is reserved for numbered parameter; consider another name
Assigning to a numbered parameter (from _1
to _9
) causes an error in Ruby 3.0.
$ ruby -ve '_1 = :value'
ruby 3.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin19]
-e:1: _1 is reserved for numbered parameter
Note
|
The parametered parameters are from _1 to _9 . This cop checks _0 , and over _10
as well to prevent confusion.
|
Examples
# bad
_1 = :value
# good
non_numbered_parameter_name = :value
Lint/OrAssignmentToConstant
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
No |
Always (Unsafe) |
1.9 |
- |
Checks for unintended or-assignment to a constant.
Constants should always be assigned in the same location. And its value
should always be the same. If constants are assigned in multiple
locations, the result may vary depending on the order of require
.
Safety
This cop is unsafe because code that is already conditionally assigning a constant may have its behavior changed by autocorrection.
Examples
# bad
CONST ||= 1
# good
CONST = 1
Lint/OrderedMagicComments
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always (Unsafe) |
0.53 |
1.37 |
Checks the proper ordering of magic comments and whether a magic comment is not placed before a shebang.
Safety
This cop’s autocorrection is unsafe because file encoding may change.
Examples
# bad
# frozen_string_literal: true
# encoding: ascii
p [''.frozen?, ''.encoding] #=> [true, #<Encoding:UTF-8>]
# good
# encoding: ascii
# frozen_string_literal: true
p [''.frozen?, ''.encoding] #=> [true, #<Encoding:US-ASCII>]
# good
#!/usr/bin/env ruby
# encoding: ascii
# frozen_string_literal: true
p [''.frozen?, ''.encoding] #=> [true, #<Encoding:US-ASCII>]
Lint/OutOfRangeRegexpRef
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
No |
No |
0.89 |
- |
Looks for references of Regexp captures that are out of range and thus always returns nil.
Safety
This cop is unsafe because it is naive in how it determines what references are available based on the last encountered regexp, but it cannot handle some cases, such as conditional regexp matches, which leads to false positives, such as:
foo ? /(c)(b)/ =~ str : /(b)/ =~ str
do_something if $2
# $2 is defined for the first condition but not the second, however
# the cop will mark this as an offense.
This might be a good indication of code that should be refactored, however.
Examples
/(foo)bar/ =~ 'foobar'
# bad - always returns nil
puts $2 # => nil
# good
puts $1 # => foo
Lint/ParenthesesAsGroupedExpression
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always |
0.12 |
0.83 |
Checks for space between the name of a called method and a left parenthesis.
Examples
# bad
do_something (foo)
# good
do_something(foo)
do_something (2 + 3) * 4
do_something (foo * ).baz
References
Lint/PercentStringArray
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
No |
Always (Unsafe) |
0.41 |
- |
Checks for quotes and commas in %w, e.g. %w('foo', "bar")
It is more likely that the additional characters are unintended (for example, mistranslating an array of literals to percent string notation) rather than meant to be part of the resulting strings.
Safety
The cop is unsafe because the correction changes the values in the array and that might have been done purposely.
%w('foo', "bar") #=> ["'foo',", '"bar"']
%w(foo bar) #=> ['foo', 'bar']
Examples
# bad
%w('foo', "bar")
# good
%w(foo bar)
Lint/PercentSymbolArray
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always |
0.41 |
- |
Checks for colons and commas in %i, e.g. %i(:foo, :bar)
It is more likely that the additional characters are unintended (for example, mistranslating an array of literals to percent string notation) rather than meant to be part of the resulting symbols.
Examples
# bad
%i(:foo, :bar)
# good
%i(foo bar)
Lint/RaiseException
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
No |
Always (Unsafe) |
0.81 |
0.86 |
Checks for raise
or fail
statements which are
raising Exception
class.
You can specify a module name that will be an implicit namespace
using AllowedImplicitNamespaces
option. The cop cause a false positive
for namespaced Exception
when a namespace is omitted. This option can
prevent the false positive by specifying a namespace to be omitted for
Exception
. Alternatively, make Exception
a fully qualified class
name with an explicit namespace.
Safety
This cop is unsafe because it will change the exception class being raised, which is a change in behavior.
Examples
# bad
raise Exception, 'Error message here'
# good
raise StandardError, 'Error message here'
AllowedImplicitNamespaces: ['Gem']
# good
module Gem
def self.foo
raise Exception # This exception means {Gem::Exception}.
end
end
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
AllowedImplicitNamespaces |
|
Array |
References
Lint/RandOne
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.36 |
- |
Checks for rand(1)
calls.
Such calls always return 0
.
Examples
# bad
rand 1
Kernel.rand(-1)
rand 1.0
rand(-1.0)
# good
0 # just use 0 instead
Lint/RedundantCopDisableDirective
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always |
0.76 |
- |
Detects instances of rubocop:disable comments that can be removed without causing any offenses to be reported. It’s implemented as a cop in that it inherits from the Cop base class and calls add_offense. The unusual part of its implementation is that it doesn’t have any on_* methods or an investigate method. This means that it doesn’t take part in the investigation phase when the other cops do their work. Instead, it waits until it’s called in a later stage of the execution. The reason it can’t be implemented as a normal cop is that it depends on the results of all other cops to do its work.
Examples
# bad
# rubocop:disable Layout/LineLength
x += 1
# rubocop:enable Layout/LineLength
# good
x += 1
Lint/RedundantCopEnableDirective
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always |
0.76 |
- |
Detects instances of rubocop:enable comments that can be removed.
When comment enables all cops at once rubocop:enable all
that cop checks whether any cop was actually enabled.
Examples
# bad
foo = 1
# rubocop:enable Layout/LineLength
# good
foo = 1
# bad
# rubocop:disable Style/StringLiterals
foo = "1"
# rubocop:enable Style/StringLiterals
baz
# rubocop:enable all
# good
# rubocop:disable Style/StringLiterals
foo = "1"
# rubocop:enable all
baz
Lint/RedundantDirGlobSort
Note
|
Required Ruby version: 3.0 |
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
Always (Unsafe) |
1.8 |
1.26 |
Sort globbed results by default in Ruby 3.0.
This cop checks for redundant sort
method to Dir.glob
and Dir[]
.
Safety
This cop is unsafe, in case of having a file and a directory with
identical names, since directory will be loaded before the file, which
will break exe/files.rb
that rely on exe.rb
file.
Examples
# bad
Dir.glob('./lib/**/*.rb').sort.each do |file|
end
Dir['./lib/**/*.rb'].sort.each do |file|
end
# good
Dir.glob('./lib/**/*.rb').each do |file|
end
Dir['./lib/**/*.rb'].each do |file|
end
Lint/RedundantRegexpQuantifiers
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
Always |
1.53 |
- |
Checks for redundant quantifiers inside Regexp literals.
It is always allowed when interpolation is used in a regexp literal, because it’s unknown what kind of string will be expanded as a result:
/(?:a*#{interpolation})?/x
Examples
# bad
/(?:x+)+/
# good
/(?:x)+/
# good
/(?:x+)/
# bad
/(?:x+)?/
# good
/(?:x)*/
# good
/(?:x*)/
Lint/RedundantRequireStatement
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always (Unsafe) |
0.76 |
1.57 |
Checks for unnecessary require
statement.
The following features are unnecessary require
statement because
they are already loaded. e.g. Ruby 2.2:
ruby -ve 'p $LOADED_FEATURES.reject { |feature| %r|/| =~ feature }'
ruby 2.2p477 (2017-09-14 revision 59906) [x86_64-darwin13]
["enumerator.so", "rational.so", "complex.so", "thread.rb"]
Below are the features that each TargetRubyVersion
targets.
-
2.0+ …
enumerator
-
2.1+ …
thread
-
2.2+ … Add
rational
andcomplex
above -
2.5+ … Add
pp
above -
2.7+ … Add
ruby2_keywords
above -
3.1+ … Add
fiber
above -
3.2+ …
set
This cop target those features.
Safety
This cop’s autocorrection is unsafe because if require 'pp'
is removed from one file,
NameError
can be encountered when another file uses PP.pp
.
Examples
# bad
require 'unloaded_feature'
require 'thread'
# good
require 'unloaded_feature'
Lint/RedundantSafeNavigation
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
No |
Always (Unsafe) |
0.93 |
- |
Checks for redundant safe navigation calls.
Use cases where a constant, named in camel case for classes and modules is nil
are rare,
and an offense is not detected when the receiver is a constant. The detection also applies
to literal receivers, except for nil
.
For all receivers, the instance_of?
, kind_of?
, is_a?
, eql?
, respond_to?
,
and equal?
methods are checked by default.
These are customizable with AllowedMethods
option.
The AllowedMethods
option specifies nil-safe methods,
in other words, it is a method that is allowed to skip safe navigation.
Note that the AllowedMethod
option is not an option that specifies methods
for which to suppress (allow) this cop’s check.
In the example below, the safe navigation operator (&.
) is unnecessary
because NilClass
has methods like respond_to?
and is_a?
.
Safety
This cop is unsafe, because autocorrection can change the return type of
the expression. An offending expression that previously could return nil
will be autocorrected to never return nil
.
Examples
# bad
CamelCaseConst&.do_something
# bad
do_something if attrs&.respond_to?(:[])
# good
do_something if attrs.respond_to?(:[])
# bad
while node&.is_a?(BeginNode)
node = node.parent
end
# good
CamelCaseConst.do_something
# good
while node.is_a?(BeginNode)
node = node.parent
end
# good - without `&.` this will always return `true`
foo&.respond_to?(:to_a)
# bad - for `nil`s conversion methods return default values for the type
foo&.to_h || {}
foo&.to_h { |k, v| [k, v] } || {}
foo&.to_a || []
foo&.to_i || 0
foo&.to_f || 0.0
foo&.to_s || ''
# good
foo.to_h
foo.to_h { |k, v| [k, v] }
foo.to_a
foo.to_i
foo.to_f
foo.to_s
AllowedMethods: [nil_safe_method]
# bad
do_something if attrs&.nil_safe_method(:[])
# good
do_something if attrs.nil_safe_method(:[])
do_something if attrs&.not_nil_safe_method(:[])
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
AllowedMethods |
|
Array |
Lint/RedundantSplatExpansion
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always |
0.76 |
1.7 |
Checks for unneeded usages of splat expansion.
Examples
# bad
a = *[1, 2, 3]
a = *'a'
a = *1
['a', 'b', *%w(c d e), 'f', 'g']
# good
c = [1, 2, 3]
a = *c
a, b = *c
a, *b = *c
a = *1..10
a = ['a']
['a', 'b', 'c', 'd', 'e', 'f', 'g']
# bad
do_something(*['foo', 'bar', 'baz'])
# good
do_something('foo', 'bar', 'baz')
# bad
begin
foo
rescue *[StandardError, ApplicationError]
end
# good
begin
foo
rescue StandardError, ApplicationError
end
# bad
case foo
when *[1, 2, 3]
else
baz
end
# good
case foo
when 1, 2, 3
else
baz
end
AllowPercentLiteralArrayArgument: true (default)
# good
do_something(*%w[foo bar baz])
AllowPercentLiteralArrayArgument: false
# bad
do_something(*%w[foo bar baz])
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
AllowPercentLiteralArrayArgument |
|
Boolean |
Lint/RedundantStringCoercion
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always |
0.19 |
0.77 |
Checks for string conversion in string interpolation, print
, puts
, and warn
arguments,
which is redundant.
Examples
# bad
"result is #{something.to_s}"
print something.to_s
puts something.to_s
warn something.to_s
# good
"result is #{something}"
print something
puts something
warn something
References
Lint/RedundantWithIndex
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always |
0.50 |
- |
Checks for redundant with_index
.
Examples
# bad
ary.each_with_index do |v|
v
end
# good
ary.each do |v|
v
end
# bad
ary.each.with_index do |v|
v
end
# good
ary.each do |v|
v
end
Lint/RedundantWithObject
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always |
0.51 |
- |
Checks for redundant with_object
.
Examples
# bad
ary.each_with_object([]) do |v|
v
end
# good
ary.each do |v|
v
end
# bad
ary.each.with_object([]) do |v|
v
end
# good
ary.each do |v|
v
end
Lint/RefinementImportMethods
Note
|
Required Ruby version: 3.1 |
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
No |
1.27 |
- |
Checks if include
or prepend
is called in refine
block.
These methods are deprecated and should be replaced with Refinement#import_methods
.
It emulates deprecation warnings in Ruby 3.1.
Safety
This cop’s autocorrection is unsafe because include M
will affect the included class
if any changes are made to module M
.
On the other hand, import_methods M
uses a snapshot of method definitions,
thus it will not be affected if module M
changes.
Examples
# bad
refine Foo do
include Bar
end
# bad
refine Foo do
prepend Bar
end
# good
refine Foo do
import_methods Bar
end
Lint/RegexpAsCondition
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always |
0.51 |
0.86 |
Checks for regexp literals used as match-current-line
.
If a regexp literal is in condition, the regexp matches $_
implicitly.
Examples
# bad
if /foo/
do_something
end
# good
if /foo/ =~ $_
do_something
end
Lint/RequireParentheses
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.18 |
- |
Checks for expressions where there is a call to a predicate method with at least one argument, where no parentheses are used around the parameter list, and a boolean operator, && or ||, is used in the last argument.
The idea behind warning for these constructs is that the user might be under the impression that the return value from the method call is an operand of &&/||.
Examples
# bad
if day.is? :tuesday && month == :jan
# ...
end
# good
if day.is?(:tuesday) && month == :jan
# ...
end
Lint/RequireRangeParentheses
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
No |
1.32 |
- |
Checks that a range literal is enclosed in parentheses when the end of the range is at a line break.
Note
|
The following is maybe intended for (42..) . But, compatible is 42..do_something .
So, this cop does not provide autocorrection because it is left to user.
|
case condition
when 42..
do_something
end
Examples
# bad - Represents `(1..42)`, not endless range.
1..
42
# good - It's incompatible, but your intentions when using endless range may be:
(1..)
42
# good
1..42
# good
(1..42)
# good
(1..
42)
Lint/RequireRelativeSelfPath
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
Always |
1.22 |
- |
Checks for uses a file requiring itself with require_relative
.
Examples
# bad
# foo.rb
require_relative 'foo'
require_relative 'bar'
# good
# foo.rb
require_relative 'bar'
Lint/RescueException
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.9 |
0.27 |
Checks for rescue
blocks targeting the Exception class.
Examples
# bad
begin
do_something
rescue Exception
handle_exception
end
# good
begin
do_something
rescue ArgumentError
handle_exception
end
References
Lint/RescueType
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always |
0.49 |
- |
Check for arguments to rescue
that will result in a TypeError
if an exception is raised.
Examples
# bad
begin
rescue nil
baz
end
# bad
def foo
rescue 1, 'a', "#{b}", 0.0, [], {}
baz
end
# good
begin
rescue
baz
end
# good
def foo
rescue NameError
baz
end
Lint/ReturnInVoidContext
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.50 |
- |
Checks for the use of a return with a value in a context where the value will be ignored. (initialize and setter methods)
Examples
# bad
def initialize
foo
return :qux if
baz
end
def foo=( )
return 42
end
# good
def initialize
foo
return if
baz
end
def foo=( )
return
end
Lint/SafeNavigationChain
Note
|
Required Ruby version: 2.3 |
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always |
0.47 |
0.77 |
The safe navigation operator returns nil if the receiver is nil. If you chain an ordinary method call after a safe navigation operator, it raises NoMethodError. We should use a safe navigation operator after a safe navigation operator. This cop checks for the problem outlined above.
Examples
# bad
x&.foo.
x&.foo +
x&.foo[ ]
# good
x&.foo&.
x&.foo ||
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
AllowedMethods |
|
Array |
Lint/SafeNavigationConsistency
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always |
0.55 |
0.77 |
Check to make sure that if safe navigation is used in an &&
or ||
condition,
consistent and appropriate safe navigation, without excess or deficiency,
is used for all method calls on the same object.
Examples
# bad
foo&. && foo&.baz
# good
foo&. && foo.baz
# bad
foo. && foo&.baz
# good
foo. && foo.baz
# bad
foo&. || foo.baz
# good
foo&. || foo&.baz
# bad
foo. || foo&.baz
# good
foo. || foo.baz
# bad
foo&. && ( .baz || foo&.baz)
# good
foo&. && ( .baz || foo.baz)
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
AllowedMethods |
|
Array |
Lint/SafeNavigationWithEmpty
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always |
0.62 |
0.87 |
Checks to make sure safe navigation isn’t used with empty?
in
a conditional.
While the safe navigation operator is generally a good idea, when
checking foo&.empty?
in a conditional, foo
being nil
will actually
do the opposite of what the author intends.
Examples
# bad
return if foo&.empty?
return unless foo&.empty?
# good
return if foo && foo.empty?
return unless foo && foo.empty?
Lint/ScriptPermission
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always |
0.49 |
0.50 |
Checks if a file which has a shebang line as its first line is granted execute permission.
Examples
# bad
# A file which has a shebang line as its first line is not
# granted execute permission.
#!/usr/bin/env ruby
puts 'hello, world'
# good
# A file which has a shebang line as its first line is
# granted execute permission.
#!/usr/bin/env ruby
puts 'hello, world'
# good
# A file which has not a shebang line as its first line is not
# granted execute permission.
puts 'hello, world'
Lint/SelfAssignment
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.89 |
- |
Checks for self-assignments.
Examples
# bad
foo = foo
foo, = foo,
Foo = Foo
hash['foo'] = hash['foo']
obj.attr = obj.attr
# good
foo =
foo, = , foo
Foo = Bar
hash['foo'] = hash['bar']
obj.attr = obj.attr2
# good (method calls possibly can return different results)
hash[foo] = hash[foo]
Lint/SendWithMixinArgument
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always |
0.75 |
- |
Checks for send
, public_send
, and send
methods
when using mix-in.
include
and prepend
methods were private methods until Ruby 2.0,
they were mixed-in via send
method. This cop uses Ruby 2.1 or
higher style that can be called by public methods.
And extend
method that was originally a public method is also targeted
for style unification.
Examples
# bad
Foo.send(:include, Bar)
Foo.send(:prepend, Bar)
Foo.send(:extend, Bar)
# bad
Foo.public_send(:include, Bar)
Foo.public_send(:prepend, Bar)
Foo.public_send(:extend, Bar)
# bad
Foo.__send__(:include, Bar)
Foo.__send__(:prepend, Bar)
Foo.__send__(:extend, Bar)
# good
Foo.include Bar
Foo.prepend Bar
Foo.extend Bar
Lint/ShadowedArgument
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.52 |
- |
Checks for shadowed arguments.
This cop has IgnoreImplicitReferences
configuration option.
It means argument shadowing is used in order to pass parameters
to zero arity super
when IgnoreImplicitReferences
is true
.
Examples
# bad
do_something do |foo|
foo = 42
puts foo
end
def do_something(foo)
foo = 42
puts foo
end
# good
do_something do |foo|
foo = foo + 42
puts foo
end
def do_something(foo)
foo = foo + 42
puts foo
end
def do_something(foo)
puts foo
end
IgnoreImplicitReferences: false (default)
# bad
def do_something(foo)
foo = 42
super
end
def do_something(foo)
foo = super
end
IgnoreImplicitReferences: true
# good
def do_something(foo)
foo = 42
super
end
def do_something(foo)
foo = super
end
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
IgnoreImplicitReferences |
|
Boolean |
Lint/ShadowedException
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.41 |
- |
Checks for a rescued exception that get shadowed by a less specific exception being rescued before a more specific exception is rescued.
An exception is considered shadowed if it is rescued after its
ancestor is, or if it and its ancestor are both rescued in the
same rescue
statement. In both cases, the more specific rescue is
unnecessary because it is covered by rescuing the less specific
exception. (ie. rescue Exception, StandardError
has the same behavior
whether StandardError
is included or not, because all StandardError
s
are rescued by rescue Exception
).
Examples
# bad
begin
something
rescue Exception
handle_exception
rescue StandardError
handle_standard_error
end
# bad
begin
something
rescue Exception, StandardError
handle_error
end
# good
begin
something
rescue StandardError
handle_standard_error
rescue Exception
handle_exception
end
# good, however depending on runtime environment.
#
# This is a special case for system call errors.
# System dependent error code depends on runtime environment.
# For example, whether {Errno::EAGAIN} and {Errno::EWOULDBLOCK} are
# the same error code or different error code depends on environment.
# This good case is for {Errno::EAGAIN} and {Errno::EWOULDBLOCK} with
# the same error code.
begin
something
rescue Errno::EAGAIN, Errno::EWOULDBLOCK
handle_standard_error
end
Lint/ShadowingOuterLocalVariable
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.9 |
- |
Checks for the use of local variable names from an outer scope
in block arguments or block-local variables. This mirrors the warning
given by ruby -cw
prior to Ruby 2.6:
"shadowing outer local variable - foo".
Note
|
Shadowing of variables in block passed to Ractor.new is allowed
because Ractor should not access outer variables.
eg. following style is encouraged:
|
worker_id, pipe = env
Ractor.new(worker_id, pipe) do |worker_id, pipe|
end
Examples
# bad
def some_method
foo = 1
2.times do |foo| # shadowing outer `foo`
do_something(foo)
end
end
# good
def some_method
foo = 1
2.times do ||
do_something( )
end
end
Lint/StructNewOverride
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.81 |
- |
Checks unexpected overrides of the Struct
built-in methods
via Struct.new
.
Examples
# bad
Bad = Struct.new(:members, :clone, :count)
b = Bad.new([], true, 1)
b.members #=> [] (overriding {Struct#members})
b.clone #=> true (overriding {Object#clone})
b.count #=> 1 (overriding {Enumerable#count})
# good
Good = Struct.new(:id, :name)
g = Good.new(1, "foo")
g.members #=> [:id, :name]
g.clone #=> #<struct Good id=1, name="foo">
g.count #=> 2
Lint/SuppressedException
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.9 |
1.12 |
Checks for rescue
blocks with no body.
Examples
# bad
def some_method
do_something
rescue
end
# bad
begin
do_something
rescue
end
# good
def some_method
do_something
rescue
handle_exception
end
# good
begin
do_something
rescue
handle_exception
end
AllowComments: true (default)
# good
def some_method
do_something
rescue
# do nothing
end
# good
begin
do_something
rescue
# do nothing
end
AllowComments: false
# bad
def some_method
do_something
rescue
# do nothing
end
# bad
begin
do_something
rescue
# do nothing
end
AllowNil: true (default)
# good
def some_method
do_something
rescue
nil
end
# good
begin
do_something
rescue
# do nothing
end
# good
do_something rescue nil
AllowNil: false
# bad
def some_method
do_something
rescue
nil
end
# bad
begin
do_something
rescue
nil
end
# bad
do_something rescue nil
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
AllowComments |
|
Boolean |
AllowNil |
|
Boolean |
References
Lint/SymbolConversion
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
Always |
1.9 |
1.16 |
Checks for uses of literal strings converted to a symbol where a literal symbol could be used instead.
There are two possible styles for this cop.
strict
(default) will register an offense for any incorrect usage.
consistent
additionally requires hashes to use the same style for
every symbol key (ie. if any symbol key needs to be quoted it requires
all keys to be quoted).
Examples
# bad
'string'.to_sym
:symbol.to_sym
'underscored_string'.to_sym
:'underscored_symbol'
'hyphenated-string'.to_sym
"string_#{interpolation}".to_sym
# good
:string
:symbol
:underscored_string
:underscored_symbol
:'hyphenated-string'
:"string_#{interpolation}"
EnforcedStyle: strict (default)
# bad
{
'a': 1,
"b": 2,
'c-d': 3
}
# good (don't quote keys that don't require quoting)
{
a: 1,
b: 2,
'c-d': 3
}
EnforcedStyle: consistent
# bad
{
a: 1,
'b-c': 2
}
# good (quote all keys if any need quoting)
{
'a': 1,
'b-c': 2
}
# good (no quoting required)
{
a: 1,
b: 2
}
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
EnforcedStyle |
|
|
Lint/Syntax
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.9 |
- |
Repacks Parser’s diagnostics/errors into RuboCop’s offenses.
Lint/ToEnumArguments
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
No |
1.1 |
- |
Ensures that to_enum
/enum_for
, called for the current method,
has correct arguments.
Examples
# bad
def foo(x, y = 1)
return to_enum(__callee__, x) # `y` is missing
end
# good
def foo(x, y = 1)
# Alternatives to `__callee__` are `__method__` and `:foo`.
return to_enum(__callee__, x, y)
end
# good
def foo(x, y = 1)
# It is also allowed if it is wrapped in some method like Sorbet.
return to_enum(T.must(__callee__), x, y)
end
Lint/ToJSON
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always |
0.66 |
- |
Checks to make sure #to_json
includes an optional argument.
When overriding #to_json
, callers may invoke JSON
generation via JSON.generate(your_obj)
. Since JSON#generate
allows
for an optional argument, your method should too.
Examples
class Point
attr_reader :x, :y
# bad, incorrect arity
def to_json
JSON.generate([x, y])
end
# good, preserving args
def to_json(*args)
JSON.generate([x, y], *args)
end
# good, discarding args
def to_json(*_args)
JSON.generate([x, y])
end
end
Lint/TopLevelReturnWithArgument
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always |
0.89 |
- |
Checks for top level return with arguments. If there is a top-level return statement with an argument, then the argument is always ignored. This is detected automatically since Ruby 2.7.
Examples
# bad
return 1
# good
return
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
Exclude |
|
Array |
Lint/TrailingCommaInAttributeDeclaration
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Command-line only |
0.90 |
1.61 |
Checks for trailing commas in attribute declarations, such as
#attr_reader
. Leaving a trailing comma will nullify the next method
definition by overriding it with a getter method.
Examples
# bad
class Foo
attr_reader :foo,
def
puts "Unreachable."
end
end
# good
class Foo
attr_reader :foo
def
puts "No problem!"
end
end
Lint/TripleQuotes
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
Always |
1.9 |
- |
Checks for "triple quotes" (strings delimited by any odd number of quotes greater than 1).
Ruby allows multiple strings to be implicitly concatenated by just
being adjacent in a statement (ie. "foo""bar" == "foobar"
). This sometimes
gives the impression that there is something special about triple quotes, but
in fact it is just extra unnecessary quotes and produces the same string. Each
pair of quotes produces an additional concatenated empty string, so the result
is still only the "actual" string within the delimiters.
Note
|
Although this cop is called triple quotes, the same behavior is present for strings delimited by 5, 7, etc. quotation marks. |
Examples
# bad
"""
A string
"""
# bad
'''
A string
'''
# good
"
A string
"
# good
<<STRING
A string
STRING
# good (but not the same spacing as the bad case)
'A string'
Lint/UnderscorePrefixedVariableName
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.21 |
- |
Checks for underscore-prefixed variables that are actually used.
Since block keyword arguments cannot be arbitrarily named at call
sites, the AllowKeywordBlockArguments
will allow use of underscore-
prefixed block keyword arguments.
Examples
AllowKeywordBlockArguments: false (default)
# bad
[1, 2, 3].each do |_num|
do_something(_num)
end
query(:sales) do |_id:, revenue:, cost:|
{_id: _id, profit: revenue - cost}
end
# good
[1, 2, 3].each do |num|
do_something(num)
end
[1, 2, 3].each do |_num|
do_something # not using `_num`
end
AllowKeywordBlockArguments: true
# good
query(:sales) do |_id:, revenue:, cost:|
{_id: _id, profit: revenue - cost}
end
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
AllowKeywordBlockArguments |
|
Boolean |
Lint/UnescapedBracketInRegexp
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
Always |
1.68 |
- |
Checks for Regexpes (both literals and via Regexp.new
/ Regexp.compile
)
that contain unescaped ]
characters.
It emulates the following Ruby warning:
$ ruby -e '/abc]123/'
-e:1: warning: regular expression has ']' without escape: /abc]123/
Examples
# bad
/abc]123/
%r{abc]123}
Regexp.new('abc]123')
Regexp.compile('abc]123')
# good
/abc\]123/
%r{abc\]123}
Regexp.new('abc\]123')
Regexp.compile('abc\]123')
Lint/UnexpectedBlockArity
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
No |
No |
1.5 |
- |
Checks for a block that is known to need more positional
block arguments than are given (by default this is configured for
Enumerable
methods needing 2 arguments). Optional arguments are allowed,
although they don’t generally make sense as the default value will
be used. Blocks that have no receiver, or take splatted arguments
(ie. *args
) are always accepted.
Keyword arguments (including **kwargs
) do not get counted towards
this, as they are not used by the methods in question.
Method names and their expected arity can be configured like this:
Methods:
inject: 2
reduce: 2
Safety
This cop matches for method names only and hence cannot tell apart methods with same name in different classes, which may lead to a false positive.
Examples
# bad
values.reduce {}
values.min { |a| a }
values.sort { |a; b| a + b }
# good
values.reduce { |memo, obj| memo << obj }
values.min { |a, b| a <=> b }
values.sort { |*x| x[0] <=> x[1] }
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
Methods |
|
Lint/UnifiedInteger
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always |
0.43 |
- |
Checks for using Fixnum or Bignum constant.
Examples
# bad
1.is_a?(Fixnum)
1.is_a?(Bignum)
# good
1.is_a?(Integer)
Lint/UnmodifiedReduceAccumulator
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
No |
1.1 |
1.5 |
Looks for reduce
or inject
blocks where the value returned (implicitly or
explicitly) does not include the accumulator. A block is considered valid as
long as at least one return value includes the accumulator.
If the accumulator is not included in the return value, then the entire block will just return a transformation of the last element value, and could be rewritten as such without a loop.
Also catches instances where an index of the accumulator is returned, as this may change the type of object being retained.
Note
|
For the purpose of reducing false positives, this cop only flags
returns in reduce blocks where the element is the only variable in
the expression (since we will not be able to tell what other variables
relate to via static analysis).
|
Examples
# bad
(1..4).reduce(0) do |acc, el|
el * 2
end
# bad, may raise a NoMethodError after the first iteration
%w(a b c).reduce({}) do |acc, letter|
acc[letter] = true
end
# good
(1..4).reduce(0) do |acc, el|
acc + el * 2
end
# good, element is returned but modified using the accumulator
values.reduce do |acc, el|
el << acc
el
end
# good, returns the accumulator instead of the index
%w(a b c).reduce({}) do |acc, letter|
acc[letter] = true
acc
end
# good, at least one branch returns the accumulator
values.reduce(nil) do |result, value|
break result if something?
value
end
# good, recursive
keys.reduce(self) { |result, key| result[key] }
# ignored as the return value cannot be determined
enum.reduce do |acc, el|
x = foo(acc, el)
(x)
end
Lint/UnreachableCode
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.9 |
- |
Checks for unreachable code.
The check are based on the presence of flow of control
statement in non-final position in begin
(implicit) blocks.
Examples
# bad
def some_method
return
do_something
end
# bad
def some_method
if cond
return
else
return
end
do_something
end
# good
def some_method
do_something
end
Lint/UnreachableLoop
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.89 |
1.7 |
Checks for loops that will have at most one iteration.
A loop that can never reach the second iteration is a possible error in the code.
In rare cases where only one iteration (or at most one iteration) is intended behavior,
the code should be refactored to use if
conditionals.
Note
|
Block methods that are used with Enumerable s are considered to be loops.
|
AllowedPatterns
can be used to match against the block receiver in order to allow
code that would otherwise be registered as an offense (eg. times
used not in an
Enumerable
context).
Examples
# bad
while node
do_something(node)
node = node.parent
break
end
# good
while node
do_something(node)
node = node.parent
end
# bad
def verify_list(head)
item = head
begin
if verify(item)
return true
else
return false
end
end while(item)
end
# good
def verify_list(head)
item = head
begin
if verify(item)
item = item.next
else
return false
end
end while(item)
true
end
# bad
def find_something(items)
items.each do |item|
if something?(item)
return item
else
raise NotFoundError
end
end
end
# good
def find_something(items)
items.each do |item|
if something?(item)
return item
end
end
raise NotFoundError
end
# bad
2.times { raise ArgumentError }
AllowedPatterns: ['(exactly|at_least|at_most)\(\d+\)\.times'] (default)
# good
exactly(2).times { raise StandardError }
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
AllowedPatterns |
|
Array |
Lint/UnusedBlockArgument
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Command-line only |
0.21 |
1.61 |
Checks for unused block arguments.
Examples
# bad
do_something do |used, unused|
puts used
end
do_something do ||
puts :foo
end
define_method(:foo) do ||
puts :baz
end
# good
do_something do |used, _unused|
puts used
end
do_something do
puts :foo
end
define_method(:foo) do ||
puts :baz
end
IgnoreEmptyBlocks: true (default)
# good
do_something { |unused| }
IgnoreEmptyBlocks: false
# bad
do_something { |unused| }
AllowUnusedKeywordArguments: false (default)
# bad
do_something do |unused: 42|
foo
end
AllowUnusedKeywordArguments: true
# good
do_something do |unused: 42|
foo
end
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
IgnoreEmptyBlocks |
|
Boolean |
AllowUnusedKeywordArguments |
|
Boolean |
Lint/UnusedMethodArgument
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Command-line only |
0.21 |
1.61 |
Checks for unused method arguments.
Examples
# bad
def some_method(used, unused, _unused_but_allowed)
puts used
end
# good
def some_method(used, _unused, _unused_but_allowed)
puts used
end
AllowUnusedKeywordArguments: false (default)
# bad
def do_something(used, unused: 42)
used
end
AllowUnusedKeywordArguments: true
# good
def do_something(used, unused: 42)
used
end
IgnoreEmptyMethods: true (default)
# good
def do_something(unused)
end
IgnoreEmptyMethods: false
# bad
def do_something(unused)
end
IgnoreNotImplementedMethods: true (default)
# good
def do_something(unused)
raise NotImplementedError
end
def do_something_else(unused)
fail "TODO"
end
IgnoreNotImplementedMethods: false
# bad
def do_something(unused)
raise NotImplementedError
end
def do_something_else(unused)
fail "TODO"
end
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
AllowUnusedKeywordArguments |
|
Boolean |
IgnoreEmptyMethods |
|
Boolean |
IgnoreNotImplementedMethods |
|
Boolean |
Lint/UriEscapeUnescape
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.50 |
- |
Identifies places where URI.escape
can be replaced by
CGI.escape
, URI.encode_www_form
, or URI.encode_www_form_component
depending on your specific use case.
Also this cop identifies places where URI.unescape
can be replaced by
CGI.unescape
, URI.decode_www_form
,
or URI.decode_www_form_component
depending on your specific use case.
Examples
# bad
URI.escape('http://example.com')
URI.encode('http://example.com')
# good
CGI.escape('http://example.com')
URI.encode_www_form([['example', 'param'], ['lang', 'en']])
URI.encode_www_form(page: 10, locale: 'en')
URI.encode_www_form_component('http://example.com')
# bad
URI.unescape(enc_uri)
URI.decode(enc_uri)
# good
CGI.unescape(enc_uri)
URI.decode_www_form(enc_uri)
URI.decode_www_form_component(enc_uri)
Lint/UriRegexp
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Always |
0.50 |
- |
Identifies places where URI.regexp
is obsolete and should not be used.
For Ruby 3.3 or lower, use URI::DEFAULT_PARSER.make_regexp
.
For Ruby 3.4 or higher, use URI::RFC2396_PARSER.make_regexp
.
Note
|
If you need to support both Ruby 3.3 and lower as well as Ruby 3.4 and higher, consider manually changing the code as follows: |
defined?(URI::RFC2396_PARSER) ? URI::RFC2396_PARSER : URI::DEFAULT_PARSER
Examples
# bad
URI.regexp('http://example.com')
# good - Ruby 3.3 or lower
URI::DEFAULT_PARSER.make_regexp('http://example.com')
# good - Ruby 3.4 or higher
URI::RFC2396_PARSER.make_regexp('http://example.com')
Lint/UselessAccessModifier
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Command-line only |
0.20 |
1.61 |
Checks for redundant access modifiers, including those with no
code, those which are repeated, and leading public
modifiers in a
class or module body. Conditionally-defined methods are considered as
always being defined, and thus access modifiers guarding such methods
are not redundant.
This cop has ContextCreatingMethods
option. The default setting value
is an empty array that means no method is specified.
This setting is an array of methods which, when called, are known to
create its own context in the module’s current access context.
It also has MethodCreatingMethods
option. The default setting value
is an empty array that means no method is specified.
This setting is an array of methods which, when called, are known to
create other methods in the module’s current access context.
Examples
# bad
class Foo
public # this is redundant (default access is public)
def method
end
end
# bad
class Foo
# The following is redundant (methods defined on the class'
# singleton class are not affected by the private modifier)
private
def self.method3
end
end
# bad
class Foo
protected
define_method(:method2) do
end
protected # this is redundant (repeated from previous modifier)
[1,2,3].each do |i|
define_method("foo#{i}") do
end
end
end
# bad
class Foo
private # this is redundant (no following methods are defined)
end
# good
class Foo
private # this is not redundant (a method is defined)
def method2
end
end
# good
class Foo
# The following is not redundant (conditionally defined methods are
# considered as always defining a method)
private
if condition?
def method
end
end
end
# good
class Foo
protected # this is not redundant (a method is defined)
define_method(:method2) do
end
end
ContextCreatingMethods: concerning
# Lint/UselessAccessModifier:
# ContextCreatingMethods:
# - concerning
# good
require 'active_support/concern'
class Foo
concerning :Bar do
def some_public_method
end
private
def some_private_method
end
end
# this is not redundant because `concerning` created its own context
private
def some_other_private_method
end
end
MethodCreatingMethods: delegate
# Lint/UselessAccessModifier:
# MethodCreatingMethods:
# - delegate
# good
require 'active_support/core_ext/module/delegation'
class Foo
# this is not redundant because `delegate` creates methods
private
delegate :method_a, to: :method_b
end
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
ContextCreatingMethods |
|
Array |
MethodCreatingMethods |
|
Array |
Lint/UselessAssignment
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Command-line only |
0.11 |
1.66 |
Checks for every useless assignment to local variable in every
scope.
The basic idea for this cop was from the warning of ruby -cw
:
assigned but unused variable - foo
Currently this cop has advanced logic that detects unreferenced reassignments and properly handles varied cases such as branch, loop, rescue, ensure, etc.
This cop’s autocorrection avoids cases like a ||= 1
because removing assignment from
operator assignment can cause NameError if this assignment has been used to declare
a local variable. For example, replacing a ||= 1
with a || 1
may cause
"undefined local variable or method `a' for main:Object (NameError)".
Note
|
Given the assignment foo = 1, bar = 2 , removing unused variables
can lead to a syntax error, so this case is not autocorrected.
|
Examples
# bad
def some_method
some_var = 1
do_something
end
# good
def some_method
some_var = 1
do_something(some_var)
end
Lint/UselessElseWithoutRescue
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
No |
0.17 |
1.31 |
Checks for useless else
in begin..end
without rescue
.
Note
|
This syntax is no longer valid on Ruby 2.6 or higher. |
Examples
# bad
begin
do_something
else
do_something_else # This will never be run.
end
# good
begin
do_something
rescue
handle_errors
else
do_something_else
end
Lint/UselessMethodDefinition
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
No |
Command-line only (Unsafe) |
0.90 |
1.61 |
Checks for useless method definitions, specifically: empty constructors
and methods just delegating to super
.
Safety
This cop is unsafe as it can register false positives for cases when an empty constructor just overrides the parent constructor, which is bad anyway.
Examples
# bad
def initialize
super
end
def method
super
end
# good - with default arguments
def initialize(x = Object.new)
super
end
# good
def initialize
super
initialize_internals
end
def method(*args)
super(:extra_arg, *args)
end
Lint/UselessNumericOperation
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
Always |
1.66 |
- |
Certain numeric operations have no impact, being: Adding or subtracting 0, multiplying or dividing by 1 or raising to the power of 1. These are probably leftover from debugging, or are mistakes.
Examples
# bad
x + 0
x - 0
x * 1
x / 1
x ** 1
# good
x
# bad
x += 0
x -= 0
x *= 1
x /= 1
x **= 1
# good
x = x
Lint/UselessRescue
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
No |
1.43 |
- |
Checks for useless `rescue`s, which only reraise rescued exceptions.
Examples
# bad
def foo
do_something
rescue
raise
end
# bad
def foo
do_something
rescue => e
raise # or 'raise e', or 'raise $!', or 'raise $ERROR_INFO'
end
# good
def foo
do_something
rescue
do_cleanup
raise
end
# bad (latest rescue)
def foo
do_something
rescue ArgumentError
# noop
rescue
raise
end
# good (not the latest rescue)
def foo
do_something
rescue ArgumentError
raise
rescue
# noop
end
Lint/UselessRuby2Keywords
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Pending |
Yes |
No |
1.23 |
- |
Looks for ruby2_keywords
calls for methods that do not need it.
ruby2_keywords
should only be called on methods that accept an argument splat
(*args
) but do not explicit keyword arguments (k:
or k: true
) or
a keyword splat (**kwargs
).
Examples
# good (splat argument without keyword arguments)
ruby2_keywords def foo(*args); end
# bad (no arguments)
ruby2_keywords def foo; end
# good
def foo; end
# bad (positional argument)
ruby2_keywords def foo(arg); end
# good
def foo(arg); end
# bad (double splatted argument)
ruby2_keywords def foo(**args); end
# good
def foo(**args); end
# bad (keyword arguments)
ruby2_keywords def foo(i:, j:); end
# good
def foo(i:, j:); end
# bad (splat argument with keyword arguments)
ruby2_keywords def foo(*args, i:, j:); end
# good
def foo(*args, i:, j:); end
# bad (splat argument with double splat)
ruby2_keywords def foo(*args, **kwargs); end
# good
def foo(*args, **kwargs); end
# bad (ruby2_keywords given a symbol)
def foo; end
ruby2_keywords :foo
# good
def foo; end
# bad (ruby2_keywords with dynamic method)
define_method(:foo) { |arg| }
ruby2_keywords :foo
# good
define_method(:foo) { |arg| }
Lint/UselessSetterCall
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
No |
Always (Unsafe) |
0.13 |
1.2 |
Checks for setter call to local variable as the final expression of a function definition.
Safety
There are edge cases in which the local variable references a value that is also accessible outside the local scope. This is not detected by the cop, and it can yield a false positive.
As well, autocorrection is unsafe because the method’s return value will be changed.
Examples
# bad
def something
x = Something.new
x.attr = 5
end
# good
def something
x = Something.new
x.attr = 5
x
end
Lint/UselessTimes
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
No |
Command-line only (Unsafe) |
0.91 |
1.61 |
Checks for uses of Integer#times
that will never yield
(when the integer ⇐ 0
) or that will only ever yield once
(1.times
).
Safety
This cop is unsafe as times
returns its receiver, which is
usually OK, but might change behavior.
Examples
# bad
-5.times { do_something }
0.times { do_something }
1.times { do_something }
1.times { |i| do_something(i) }
# good
do_something
do_something(1)
Lint/Void
Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed |
---|---|---|---|---|
Enabled |
Yes |
Command-line only |
0.9 |
1.61 |
Checks for operators, variables, literals, lambda, proc and nonmutating methods used in void context.
each
blocks are allowed to prevent false positives.
For example, the expression inside the each
block below.
It’s not void, especially when the receiver is an Enumerator
:
enumerator = [1, 2, 3].filter
enumerator.each { |item| item >= 2 } #=> [2, 3]
Examples
CheckForMethodsWithNoSideEffects: false (default)
# bad
def some_method
some_num * 10
do_something
end
def some_method(some_var)
some_var
do_something
end
CheckForMethodsWithNoSideEffects: true
# bad
def some_method(some_array)
some_array.sort
do_something(some_array)
end
# good
def some_method
do_something
some_num * 10
end
def some_method(some_var)
do_something
some_var
end
def some_method(some_array)
some_array.sort!
do_something(some_array)
end
Configurable attributes
Name | Default value | Configurable values |
---|---|---|
CheckForMethodsWithNoSideEffects |
|
Boolean |