Lint

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

No

0.48

1.13

Checks for ambiguous block association with method when param passed without parentheses.

This cop can customize ignored methods with IgnoredMethods.

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 == bar { |b| b.baz }

# good
# Lambda arguments require no disambiguation
foo = ->(bar) { bar.baz }

IgnoredMethods: [change]

# good
expect { do_something }.to change { object.attribute }

Configurable attributes

Name Default value Configurable values

IgnoredMethods

[]

Array

Lint/AmbiguousOperator

Enabled by default Safe Supports autocorrection Version Added Version Changed

Enabled

Yes

Yes

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

Yes

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.

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

Yes (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.

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'
:bar..: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.bar
(a.foo)..(b.bar)

RequireParenthesesForMethodChains: true

# bad
a.foo..b.bar

# good
(a.foo)..(b.bar)

Configurable attributes

Name Default value Configurable values

RequireParenthesesForMethodChains

false

Boolean

Lint/AmbiguousRegexpLiteral

Enabled by default Safe Supports autocorrection Version Added Version Changed

Enabled

Yes

Yes

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

No

0.9

-

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."

Examples

# bad
if some_var = true
  do_something
end

# good
if some_var == true
  do_something
end

AllowSafeAssignment: true (default)

# good
if (some_var = true)
  do_something
end

AllowSafeAssignment: false

# bad
if (some_var = true)
  do_something
end

Configurable attributes

Name Default value Configurable values

AllowSafeAssignment

true

Boolean

Lint/BigDecimalNew

Enabled by default Safe Supports autocorrection Version Added Version Changed

Enabled

Yes

Yes

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

Yes (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

enums

Array

Lint/ConstantOverwrittenInRescue

Enabled by default Safe Supports autocorrection Version Added Version Changed

Pending

Yes

Yes

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]

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.10

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:
  WebConsole: ~

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

Configurable attributes

Name Default value Configurable values

DebuggerReceivers

[]

Array

DebuggerMethods

{"Kernel"⇒["binding.irb"], "Byebug"⇒["byebug", "remote_byebug", "Kernel.byebug", "Kernel.remote_byebug"], "Capybara"⇒["save_and_open_page", "save_and_open_screenshot"], "debug.rb"⇒["binding.b", "binding.break", "Kernel.binding.b", "Kernel.binding.break"], "Pry"⇒["binding.pry", "binding.remote_pry", "binding.pry_remote", "Pry.rescue"], "Rails"⇒["debugger", "Kernel.debugger"], "RubyJard"⇒["jard"], "WebConsole"⇒["binding.console"]}

Lint/DeprecatedClassMethods

Enabled by default Safe Supports autocorrection Version Added Version Changed

Enabled

Yes

Yes

0.19

-

Checks for uses of the deprecated class method usages.

Examples

# bad

File.exists?(some_path)
Dir.exists?(some_path)
iterator?
ENV.freeze # Calling `Env.freeze` raises `TypeError` since Ruby 2.7.
Socket.gethostbyname(host)
Socket.gethostbyaddr(host)
# good

File.exist?(some_path)
Dir.exist?(some_path)
block_given?
ENV # `ENV.freeze` cannot prohibit changes to environment variables.
Addrinfo.getaddrinfo(nodename, service)
Addrinfo.tcp(host, port).getnameinfo

Lint/DeprecatedConstants

Enabled by default Safe Supports autocorrection Version Added Version Changed

Pending

Yes

Yes

1.8

1.22

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 and Random::DEFAULT are configured.

Examples

# bad
NIL
TRUE
FALSE
Random::DEFAULT # Return value of Ruby 2 is `Random` instance, Ruby 3.0 is `Random` class.

# good
nil
true
false
Random.new # `::DEFAULT` has been deprecated in Ruby 3, `.new` is compatible with Ruby 2.

Configurable attributes

Name Default value Configurable values

DeprecatedConstants

{"NIL"⇒{"Alternative"⇒"nil", "DeprecatedVersion"⇒"2.4"}, "TRUE"⇒{"Alternative"⇒"true", "DeprecatedVersion"⇒"2.4"}, "FALSE"⇒{"Alternative"⇒"false", "DeprecatedVersion"⇒"2.4"}, "Net::HTTPServerException"⇒{"Alternative"⇒"Net::HTTPClientException", "DeprecatedVersion"⇒"2.6"}, "Random::DEFAULT"⇒{"Alternative"⇒"Random.new", "DeprecatedVersion"⇒"3.0"}}

Lint/DeprecatedOpenSSLConstant

Enabled by default Safe Supports autocorrection Version Added Version Changed

Enabled

Yes

Yes

0.84

-

Algorithmic constants for OpenSSL::Cipher and OpenSSL::Digest deprecated since OpenSSL version 2.2.0. Prefer passing a string instead.

Examples

# Example for OpenSSL::Cipher instantiation.

# bad
OpenSSL::Cipher::AES.new(128, :GCM)

# good
OpenSSL::Cipher.new('aes-128-gcm')
# Example for OpenSSL::Digest instantiation.

# bad
OpenSSL::Digest::SHA256.new

# good
OpenSSL::Digest.new('SHA256')
# Example for ::Digest inherited class methods.

# 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

Yes (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.

Examples

# bad
if foo
  do_foo
  do_something_else
elsif bar
  do_foo
  do_something_else
end

# good
if foo || bar
  do_foo
  do_something_else
end

# bad
case x
when foo
  do_foo
when bar
  do_foo
else
  do_something_else
end

# good
case x
when foo, bar
  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

Configurable attributes

Name Default value Configurable values

IgnoreLiteralBranches

false

Boolean

IgnoreConstantBranches

false

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 mirrors a warning in Ruby 2.2.

Examples

# bad

hash = { food: 'apple', food: 'orange' }
# good

hash = { food: 'apple', other_food: 'orange' }

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 bar
# good

def foo
  1
end

def bar
  2
end
# good

def foo
  1
end

alias bar foo

Lint/DuplicateRegexpCharacterClassElement

Enabled by default Safe Supports autocorrection Version Added Version Changed

Pending

Yes

Yes

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

Yes (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/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

Yes

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 be clearer what we’re aiming for.

Empty lambdas and procs are ignored by default.

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

true

Boolean

AllowEmptyLambdas

true

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 :bar
  end
end

class << obj
  attr_reader :bar
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

false

Boolean

Lint/EmptyConditionalBody

Enabled by default Safe Supports autocorrection Version Added Version Changed

Enabled

Yes

No

0.89

-

Checks for the presence of if, elsif and unless branches without a body.

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

true

Boolean

Lint/EmptyEnsure

Enabled by default Safe Supports autocorrection Version Added Version Changed

Enabled

Yes

Yes

0.10

0.48

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 ()
  bar
end
# good

foo = (some_expression)
if (some_expression)
  bar
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

true

Boolean

Lint/EmptyInPattern

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

true

Boolean

Lint/EmptyInterpolation

Enabled by default Safe Supports autocorrection Version Added Version Changed

Enabled

Yes

Yes

0.20

0.45

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 bar
  do_something
when baz
end
# good
case condition
when foo
  do_something
when bar
  nil
end

AllowComments: true (default)

# good
case condition
when foo
  do_something
when bar
  # noop
end

AllowComments: false

# bad
case condition
when foo
  do_something
when bar
  # do nothing
end

Configurable attributes

Name Default value Configurable values

AllowComments

true

Boolean

Lint/EnsureReturn

Enabled by default Safe Supports autocorrection Version Added Version Changed

Enabled

Yes

Yes

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

# also good

def foo
  begin
    do_something
  rescue SomeException
    # Let's ignore this exception
  end
  self
ensure
  cleanup
end

Lint/ErbNewArguments

Required Ruby version: 2.6
Enabled by default Safe Supports autocorrection Version Added Version Changed

Enabled

Yes

Yes

0.56

-

This cop 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

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
(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/

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] = :bar
hash.key?(baz.object_id)

# good
hash = {}.compare_by_identity
hash[foo] = :bar
hash.key?(baz)

Lint/HeredocMethodCallPosition

Enabled by default Safe Supports autocorrection Version Added Version Changed

Disabled

Yes

Yes

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

Lint/IdentityComparison

Enabled by default Safe Supports autocorrection Version Added Version Changed

Enabled

Yes

Yes

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 == bar.object_id

# good
foo.equal?(bar)

Lint/ImplicitStringConcatenation

Enabled by default Safe Supports autocorrection Version Added Version Changed

Enabled

Yes

No

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

Yes (Unsafe)

1.21

1.24

This cop checks for IO.select that is incompatible with Fiber Scheduler since Ruby 3.0.

When the method is successful the return value of IO.select is , and the return value of io.wait_readable and io.wait_writable are self. They are not autocorrected when assigning a return value because these types are different. It’s up to user how to handle the return value.

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

Yes (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

standard_error

standard_error, runtime_error

Lint/InterpolationCheck

Enabled by default Safe Supports autocorrection Version Added Version Changed

Enabled

No

Yes (Unsafe)

0.50

0.87

Checks for interpolation in a single quoted string.

Safety

This cop is generally safe, but is marked as unsafe because it is possible to actually intentionally have text inside #{…​} in a single quoted string.

Examples

# bad

foo = 'something with #{interpolation} inside'
# good

foo = "something with #{interpolation} inside"

Lint/LambdaWithoutLiteralBlock

Enabled by default Safe Supports autocorrection Version Added Version Changed

Pending

Yes

Yes

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.0.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.

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/LiteralInInterpolation

Enabled by default Safe Supports autocorrection Version Added Version Changed

Enabled

Yes

Yes

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

Yes (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
# bad

# using until
begin
  do_something
end until some_condition
# good

# while replacement
loop do
  do_something
  break unless some_condition
end
# good

# until replacement
loop do
  do_something
  break if some_condition
end

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

Infinity

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.

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
class Parent
  def self.inherited(base)
    do_something
  end
end

# good
class Parent
  def self.inherited(base)
    super
    do_something
  end
end

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.

# 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

Yes

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 bar
  end
end
# good

def foo
  bar = -> { puts 'hello' }
  bar.call
end
# good

def foo
  self.class.class_eval do
    def bar
    end
  end
end

def foo
  self.class.module_exec do
    def bar
    end
  end
end
# good

def foo
  class << self
    def bar
    end
  end
end

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

Yes (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
unless FileTest.exist?(path)
  FileUtils.makedirs(path)
end

if FileTest.exist?(path)
  FileUtils.remove(path)
end

# good
FileUtils.mkdir_p(path)

FileUtils.rm_rf(path)

Lint/NonDeterministicRequireOrder

Enabled by default Safe Supports autocorrection Version Added Version Changed

Enabled

No

Yes (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.

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 or define_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.message # allowed
      "#{error.param}: #{error.message}"
    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

Yes (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.

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 ignored with IgnoredMethods.

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)
bar.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) }
bar.send { |i| Complex(i) }

IgnoredMethods: [minutes]

# good
10.minutes.to_i

IgnoredClasses: [Time, DateTime] (default)

# good
Time.now.to_datetime.to_i

Configurable attributes

Name Default value Configurable values

IgnoredMethods

[]

Array

IgnoredClasses

Time, DateTime

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.7.2p137 (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.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin19]
-e:1: _1 is reserved for numbered parameter
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

Yes (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

Yes

0.53

-

Checks the proper ordering of magic comments and whether a magic comment is not placed before a shebang.

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

-

This cops 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

Yes

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 * bar).baz

Lint/PercentStringArray

Enabled by default Safe Supports autocorrection Version Added Version Changed

Enabled

No

Yes (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

Yes

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

Yes (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

Gem

Array

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

Yes

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

Yes

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

Required Ruby version: 3.0
Enabled by default Safe Supports autocorrection Version Added Version Changed

Pending

Yes

Yes (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/RedundantRequireStatement

Required Ruby version: 2.2
Enabled by default Safe Supports autocorrection Version Added Version Changed

Enabled

Yes

Yes

0.76

-

Checks for unnecessary require statement.

The following features are unnecessary require statement because they are already loaded.

ruby -ve 'p $LOADED_FEATURES.reject { |feature| %r|/| =~ feature }'
ruby 2.2.8p477 (2017-09-14 revision 59906) [x86_64-darwin13]
["enumerator.so", "rational.so", "complex.so", "thread.rb"]

This cop targets Ruby 2.2 or higher containing these 4 features.

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

Yes (Unsafe)

0.93

-

Checks for redundant safe navigation calls. instance_of?, kind_of?, is_a?, eql?, respond_to?, and equal? methods are checked by default. These are customizable with AllowedMethods option.

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
do_something if attrs&.respond_to?(:[])

# good
do_something if attrs.respond_to?(:[])

# bad
while node&.is_a?(BeginNode)
  node = node.parent
end

# good
while node.is_a?(BeginNode)
  node = node.parent
end

# good - without `&.` this will always return `true`
foo&.respond_to?(:to_a)

Configurable attributes

Name Default value Configurable values

AllowedMethods

instance_of?, kind_of?, is_a?, eql?, respond_to?, equal?

Array

Lint/RedundantSplatExpansion

Enabled by default Safe Supports autocorrection Version Added Version Changed

Enabled

Yes

Yes

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]
  bar
end

# good
begin
  foo
rescue StandardError, ApplicationError
  bar
end

# bad
case foo
when *[1, 2, 3]
  bar
else
  baz
end

# good
case foo
when 1, 2, 3
  bar
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

true

Boolean

Lint/RedundantStringCoercion

Enabled by default Safe Supports autocorrection Version Added Version Changed

Enabled

Yes

Yes

0.19

0.77

Checks for string conversion in string interpolation, which is redundant.

Examples

# bad

"result is #{something.to_s}"
# good

"result is #{something}"

Lint/RedundantWithIndex

Enabled by default Safe Supports autocorrection Version Added Version Changed

Enabled

Yes

Yes

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

Yes

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

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

Yes

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/RequireRelativeSelfPath

Enabled by default Safe Supports autocorrection Version Added Version Changed

Pending

Yes

Yes

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

Lint/RescueType

Enabled by default Safe Supports autocorrection Version Added Version Changed

Enabled

Yes

Yes

0.49

-

Check for arguments to rescue that will result in a TypeError if an exception is raised.

Examples

# bad
begin
  bar
rescue nil
  baz
end

# bad
def foo
  bar
rescue 1, 'a', "#{b}", 0.0, [], {}
  baz
end

# good
begin
  bar
rescue
  baz
end

# good
def foo
  bar
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 bar?
  baz
end

def foo=(bar)
  return 42
end
# good
def initialize
  foo
  return if bar?
  baz
end

def foo=(bar)
  return
end

Lint/SafeNavigationChain

Required Ruby version: 2.3
Enabled by default Safe Supports autocorrection Version Added Version Changed

Enabled

Yes

No

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.bar
x&.foo + bar
x&.foo[bar]
# good

x&.foo&.bar
x&.foo || bar

Configurable attributes

Name Default value Configurable values

AllowedMethods

present?, blank?, presence, try, try!, in?

Array

Lint/SafeNavigationConsistency

Enabled by default Safe Supports autocorrection Version Added Version Changed

Enabled

Yes

Yes

0.55

0.77

Check to make sure that if safe navigation is used for a method call in an && or || condition that safe navigation is used for all method calls on that same object.

Examples

# bad
foo&.bar && foo.baz

# bad
foo.bar || foo&.baz

# bad
foo&.bar && (foobar.baz || foo.baz)

# good
foo.bar && foo.baz

# good
foo&.bar || foo&.baz

# good
foo&.bar && (foobar.baz || foo&.baz)

Configurable attributes

Name Default value Configurable values

AllowedMethods

present?, blank?, presence, try, try!

Array

Lint/SafeNavigationWithEmpty

Enabled by default Safe Supports autocorrection Version Added Version Changed

Enabled

Yes

Yes

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

Yes

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, bar = foo, bar
Foo = Foo

# good
foo = bar
foo, bar = bar, foo
Foo = Bar

Lint/SendWithMixinArgument

Enabled by default Safe Supports autocorrection Version Added Version Changed

Enabled

Yes

Yes

0.75

-

This cop 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
  bar
end

IgnoreImplicitReferences: true

# good
def do_something(foo)
  foo = 42
  super
end

def do_something(foo)
  foo = super
  bar
end

Configurable attributes

Name Default value Configurable values

IgnoreImplicitReferences

false

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.

Examples

# bad

begin
  something
rescue Exception
  handle_exception
rescue StandardError
  handle_standard_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".

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 |bar|
    do_something(bar)
  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

true

Boolean

AllowNil

true

Boolean

Lint/SymbolConversion

Enabled by default Safe Supports autocorrection Version Added Version Changed

Pending

Yes

Yes

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

# good
:string
:symbol
:underscored_string
:underscored_symbol
:'hyphenated-string'

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

strict

strict, consistent

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)
  return to_enum(__callee__, x, y)
  # alternatives to `__callee__` are `__method__` and `:foo`
end

Lint/ToJSON

Enabled by default Safe Supports autocorrection Version Added Version Changed

Enabled

Yes

Yes

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

No

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

# Detected since Ruby 2.7
return 1 # 1 is always ignored.

Lint/TrailingCommaInAttributeDeclaration

Enabled by default Safe Supports autocorrection Version Added Version Changed

Enabled

Yes

Yes

0.90

-

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 bar
    puts "Unreachable."
  end
end

# good
class Foo
  attr_reader :foo

  def bar
    puts "No problem!"
  end
end

Lint/TripleQuotes

Enabled by default Safe Supports autocorrection Version Added Version Changed

Pending

Yes

Yes

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.

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

false

Boolean

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

{"chunk_while"⇒2, "each_with_index"⇒2, "each_with_object"⇒2, "inject"⇒2, "max"⇒2, "min"⇒2, "minmax"⇒2, "reduce"⇒2, "slice_when"⇒2, "sort"⇒2}

Lint/UnifiedInteger

Enabled by default Safe Supports autocorrection Version Added Version Changed

Enabled

Yes

Yes

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.

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)
  bar(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.

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

`(?-mix:(exactly

at_least

at_most)\(\d+\)\.times)`

Array

IgnoredPatterns

Lint/UnusedBlockArgument

Enabled by default Safe Supports autocorrection Version Added Version Changed

Enabled

Yes

Yes

0.21

0.22

Checks for unused block arguments.

Examples

# bad
do_something do |used, unused|
  puts used
end

do_something do |bar|
  puts :foo
end

define_method(:foo) do |bar|
  puts :baz
end

# good
do_something do |used, _unused|
  puts used
end

do_something do
  puts :foo
end

define_method(:foo) do |_bar|
  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

true

Boolean

AllowUnusedKeywordArguments

false

Boolean

Lint/UnusedMethodArgument

Enabled by default Safe Supports autocorrection Version Added Version Changed

Enabled

Yes

Yes

0.21

0.81

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

false

Boolean

IgnoreEmptyMethods

true

Boolean

IgnoreNotImplementedMethods

true

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

Yes

0.50

-

Identifies places where URI.regexp is obsolete and should not be used. Instead, use URI::DEFAULT_PARSER.make_regexp.

Examples

# bad
URI.regexp('http://example.com')

# good
URI::DEFAULT_PARSER.make_regexp('http://example.com')

Lint/UselessAccessModifier

Enabled by default Safe Supports autocorrection Version Added Version Changed

Enabled

Yes

Yes

0.20

0.83

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 public modifier)
  public

  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

No

0.11

-

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.

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.

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

Yes (Unsafe)

0.90

0.91

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/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

Yes (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

Yes (Unsafe)

0.91

-

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

No

0.9

-

Checks for operators, variables, literals, and nonmutating methods used in void context.

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

false

Boolean