Showing 96 of 98 total issues
Omit the hash value. Open
output_byte_count: output_byte_count,
- Read upRead up
- Exclude checks
Checks hash literal syntax.
It can enforce either the use of the class hash rocket syntax or the use of the newer Ruby 1.9 syntax (when applicable).
A separate offense is registered for each problematic pair.
The supported styles are:
- ruby19 - forces use of the 1.9 syntax (e.g.
{a: 1}
) when hashes have all symbols for keys - hash_rockets - forces use of hash rockets for all hashes
- nomixedkeys - simply checks for hashes with mixed syntaxes
- ruby19nomixed_keys - forces use of ruby 1.9 syntax and forbids mixed syntax hashes
This cop has EnforcedShorthandSyntax
option.
It can enforce either the use of the explicit hash value syntax or
the use of Ruby 3.1's hash value shorthand syntax.
The supported styles are:
- always - forces use of the 3.1 syntax (e.g. {foo:})
- never - forces use of explicit hash literal value
- either - accepts both shorthand and explicit use of hash literal value
Example: EnforcedStyle: ruby19 (default)
# bad
{:a => 2}
{b: 1, :c => 2}
# good
{a: 2, b: 1}
{:c => 2, 'd' => 2} # acceptable since 'd' isn't a symbol
{d: 1, 'e' => 2} # technically not forbidden
Example: EnforcedStyle: hash_rockets
# bad
{a: 1, b: 2}
{c: 1, 'd' => 5}
# good
{:a => 1, :b => 2}
Example: EnforcedStyle: nomixedkeys
# bad
{:a => 1, b: 2}
{c: 1, 'd' => 2}
# good
{:a => 1, :b => 2}
{c: 1, d: 2}
Example: EnforcedStyle: ruby19nomixed_keys
# bad
{:a => 1, :b => 2}
{c: 2, 'd' => 3} # should just use hash rockets
# good
{a: 1, b: 2}
{:c => 3, 'd' => 4}
Example: EnforcedShorthandSyntax: always (default)
# bad
{foo: foo, bar: bar}
# good
{foo:, bar:}
Example: EnforcedShorthandSyntax: never
# bad
{foo:, bar:}
# good
{foo: foo, bar: bar}
Example: EnforcedShorthandSyntax: either
# good
{foo: foo, bar: bar}
# good
{foo:, bar:}
Call super
to initialize state of the parent class. Open
def initialize(failure_ex, timeout_ex = nil, maximum_output_ex = nil)
@failure_ex = failure_ex
@timeout_ex = timeout_ex || failure_ex
@maximum_output_ex = maximum_output_ex || failure_ex
end
- Read upRead up
- Exclude checks
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.
Example:
# 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
When using method_missing
, define respond_to_missing?
. Open
def method_missing(*)
yield if block_given?
end
- Read upRead up
- Exclude checks
Checks for the presence of method_missing
without also
defining respond_to_missing?
.
Example:
#bad
def method_missing(name, *args)
# ...
end
#good
def respond_to_missing?(name, include_private)
# ...
end
def method_missing(name, *args)
# ...
end
Operator ||
should be surrounded by a single space. Open
YAML.safe_load(f, permitted_classes: [Time], permitted_symbols: [], aliases: false, filename: self.class::FILE_NAME) || {}
- Read upRead up
- Exclude checks
Checks that operators have space around them, except for ** which should or shouldn't have surrounding space depending on configuration. It allows vertical alignment consisting of one or more whitespace around operators.
This cop has AllowForAlignment
option. When true
, allows most
uses of extra spacing if the intent is to align with an operator on
the previous or next line, not counting empty lines or comment lines.
Example:
# bad
total = 3*4
"apple"+"juice"
my_number = 38/4
# good
total = 3 * 4
"apple" + "juice"
my_number = 38 / 4
Example: AllowForAlignment: true (default)
# good
{
1 => 2,
11 => 3
}
Example: AllowForAlignment: false
# bad
{
1 => 2,
11 => 3
}
Example: EnforcedStyleForExponentOperator: no_space (default)
# bad
a ** b
# good
a**b
Example: EnforcedStyleForExponentOperator: space
# bad
a**b
# good
a ** b
Prefer do...end
over {...}
for procedural blocks. Open
::CC::Resolv.with_fixed_dns { fetch_all }
- Read upRead up
- Exclude checks
Check for uses of braces or do/end around single line or multi-line blocks.
Methods that can be either procedural or functional and cannot be
categorised from their usage alone is ignored.
lambda
, proc
, and it
are their defaults.
Additional methods can be added to the IgnoredMethods
.
Example: EnforcedStyle: linecountbased (default)
# bad - single line block
items.each do |item| item / 5 end
# good - single line block
items.each { |item| item / 5 }
# bad - multi-line block
things.map { |thing|
something = thing.some_method
process(something)
}
# good - multi-line block
things.map do |thing|
something = thing.some_method
process(something)
end
Example: EnforcedStyle: semantic
# Prefer `do...end` over `{...}` for procedural blocks.
# return value is used/assigned
# bad
foo = map do |x|
x
end
puts (map do |x|
x
end)
# return value is not used out of scope
# good
map do |x|
x
end
# Prefer `{...}` over `do...end` for functional blocks.
# return value is not used out of scope
# bad
each { |x|
x
}
# return value is used/assigned
# good
foo = map { |x|
x
}
map { |x|
x
}.inspect
# The AllowBracesOnProceduralOneLiners option is ignored unless the
# EnforcedStyle is set to `semantic`. If so:
# If the AllowBracesOnProceduralOneLiners option is unspecified, or
# set to `false` or any other falsey value, then semantic purity is
# maintained, so one-line procedural blocks must use do-end, not
# braces.
# bad
collection.each { |element| puts element }
# good
collection.each do |element| puts element end
# If the AllowBracesOnProceduralOneLiners option is set to `true`, or
# any other truthy value, then one-line procedural blocks may use
# either style. (There is no setting for requiring braces on them.)
# good
collection.each { |element| puts element }
# also good
collection.each do |element| puts element end
Example: EnforcedStyle: bracesforchaining
# bad
words.each do |word|
word.flip.flop
end.join("-")
# good
words.each { |word|
word.flip.flop
}.join("-")
Example: EnforcedStyle: always_braces
# bad
words.each do |word|
word.flip.flop
end
# good
words.each { |word|
word.flip.flop
}
Example: BracesRequiredMethods: ['sig']
# Methods listed in the BracesRequiredMethods list, such as 'sig'
# in this example, will require `{...}` braces. This option takes
# precedence over all other configurations except IgnoredMethods.
# bad
sig do
params(
foo: string,
).void
end
def bar(foo)
puts foo
end
# good
sig {
params(
foo: string,
).void
}
def bar(foo)
puts foo
end
Example: IgnoredMethods: ['lambda', 'proc', 'it' ] (default)
# good
foo = lambda do |x|
puts "Hello, #{x}"
end
foo = lambda do |x|
x * 100
end
Use e
instead of ex
. Open
rescue FetchError, InternalHostError => ex
- Read upRead up
- Exclude checks
Makes sure that rescued exceptions variables are named as expected.
The PreferredName
config option takes a String
. It represents
the required name of the variable. Its default is e
.
NOTE: This cop does not consider nested rescues because it cannot guarantee that the variable from the outer rescue is not used within the inner rescue (in which case, changing the inner variable would shadow the outer variable).
Example: PreferredName: e (default)
# bad
begin
# do something
rescue MyException => exception
# do something
end
# good
begin
# do something
rescue MyException => e
# do something
end
# good
begin
# do something
rescue MyException => _e
# do something
end
Example: PreferredName: exception
# bad
begin
# do something
rescue MyException => e
# do something
end
# good
begin
# do something
rescue MyException => exception
# do something
end
# good
begin
# do something
rescue MyException => _exception
# do something
end
Use expand_path('../../../VERSION', __dir__)
instead of expand_path('../../../../VERSION', __FILE__)
. Open
path = File.expand_path("../../../../VERSION", __FILE__)
- Read upRead up
- Exclude checks
Checks for use of the File.expand_path
arguments.
Likewise, it also checks for the Pathname.new
argument.
Contrastive bad case and good case are alternately shown in the following examples.
Example:
# bad
File.expand_path('..', __FILE__)
# good
File.expand_path(__dir__)
# bad
File.expand_path('../..', __FILE__)
# good
File.expand_path('..', __dir__)
# bad
File.expand_path('.', __FILE__)
# good
File.expand_path(__FILE__)
# bad
Pathname(__FILE__).parent.expand_path
# good
Pathname(__dir__).expand_path
# bad
Pathname.new(__FILE__).parent.expand_path
# good
Pathname.new(__dir__).expand_path
Use e
instead of error
. Open
rescue JSON::ParserError => error
- Read upRead up
- Exclude checks
Makes sure that rescued exceptions variables are named as expected.
The PreferredName
config option takes a String
. It represents
the required name of the variable. Its default is e
.
NOTE: This cop does not consider nested rescues because it cannot guarantee that the variable from the outer rescue is not used within the inner rescue (in which case, changing the inner variable would shadow the outer variable).
Example: PreferredName: e (default)
# bad
begin
# do something
rescue MyException => exception
# do something
end
# good
begin
# do something
rescue MyException => e
# do something
end
# good
begin
# do something
rescue MyException => _e
# do something
end
Example: PreferredName: exception
# bad
begin
# do something
rescue MyException => e
# do something
end
# good
begin
# do something
rescue MyException => exception
# do something
end
# good
begin
# do something
rescue MyException => _exception
# do something
end
Prefer {...}
over do...end
for functional blocks. Open
data.fetch("other_locations", []).map do |loc|
- Read upRead up
- Exclude checks
Check for uses of braces or do/end around single line or multi-line blocks.
Methods that can be either procedural or functional and cannot be
categorised from their usage alone is ignored.
lambda
, proc
, and it
are their defaults.
Additional methods can be added to the IgnoredMethods
.
Example: EnforcedStyle: linecountbased (default)
# bad - single line block
items.each do |item| item / 5 end
# good - single line block
items.each { |item| item / 5 }
# bad - multi-line block
things.map { |thing|
something = thing.some_method
process(something)
}
# good - multi-line block
things.map do |thing|
something = thing.some_method
process(something)
end
Example: EnforcedStyle: semantic
# Prefer `do...end` over `{...}` for procedural blocks.
# return value is used/assigned
# bad
foo = map do |x|
x
end
puts (map do |x|
x
end)
# return value is not used out of scope
# good
map do |x|
x
end
# Prefer `{...}` over `do...end` for functional blocks.
# return value is not used out of scope
# bad
each { |x|
x
}
# return value is used/assigned
# good
foo = map { |x|
x
}
map { |x|
x
}.inspect
# The AllowBracesOnProceduralOneLiners option is ignored unless the
# EnforcedStyle is set to `semantic`. If so:
# If the AllowBracesOnProceduralOneLiners option is unspecified, or
# set to `false` or any other falsey value, then semantic purity is
# maintained, so one-line procedural blocks must use do-end, not
# braces.
# bad
collection.each { |element| puts element }
# good
collection.each do |element| puts element end
# If the AllowBracesOnProceduralOneLiners option is set to `true`, or
# any other truthy value, then one-line procedural blocks may use
# either style. (There is no setting for requiring braces on them.)
# good
collection.each { |element| puts element }
# also good
collection.each do |element| puts element end
Example: EnforcedStyle: bracesforchaining
# bad
words.each do |word|
word.flip.flop
end.join("-")
# good
words.each { |word|
word.flip.flop
}.join("-")
Example: EnforcedStyle: always_braces
# bad
words.each do |word|
word.flip.flop
end
# good
words.each { |word|
word.flip.flop
}
Example: BracesRequiredMethods: ['sig']
# Methods listed in the BracesRequiredMethods list, such as 'sig'
# in this example, will require `{...}` braces. This option takes
# precedence over all other configurations except IgnoredMethods.
# bad
sig do
params(
foo: string,
).void
end
def bar(foo)
puts foo
end
# good
sig {
params(
foo: string,
).void
}
def bar(foo)
puts foo
end
Example: IgnoredMethods: ['lambda', 'proc', 'it' ] (default)
# good
foo = lambda do |x|
puts "Hello, #{x}"
end
foo = lambda do |x|
x * 100
end
Prefer transform_values
over each_with_object
. Open
positions.each_with_object({}) do |(key, value), memo|
memo[key] =
if value.key?("offset")
value
else
- Read upRead up
- Exclude checks
Looks for uses of _.each_with_object({}) {...}
,
_.map {...}.to_h
, and Hash[_.map {...}]
that are actually just
transforming the values of a hash, and tries to use a simpler & faster
call to transform_values
instead.
Safety:
This cop is unsafe, as it can produce false positives if we are
transforming an enumerable of key-value-like pairs that isn't actually
a hash, e.g.: [[k1, v1], [k2, v2], ...]
Example:
# bad
{a: 1, b: 2}.each_with_object({}) { |(k, v), h| h[k] = foo(v) }
Hash[{a: 1, b: 2}.collect { |k, v| [k, foo(v)] }]
{a: 1, b: 2}.map { |k, v| [k, v * v] }.to_h
{a: 1, b: 2}.to_h { |k, v| [k, v * v] }
# good
{a: 1, b: 2}.transform_values { |v| foo(v) }
{a: 1, b: 2}.transform_values { |v| v * v }
Use $stderr
instead of STDERR
. Open
@logger ||= ::Logger.new(STDERR).tap do |logger|
- Read upRead up
- Exclude checks
Enforces the use of $stdout/$stderr/$stdin
instead of STDOUT/STDERR/STDIN
.
STDOUT/STDERR/STDIN
are constants, and while you can actually
reassign (possibly to redirect some stream) constants in Ruby, you'll get
an interpreter warning if you do so.
Safety:
Autocorrection is unsafe because STDOUT
and $stdout
may point to different
objects, for example.
Example:
# bad
STDOUT.puts('hello')
hash = { out: STDOUT, key: value }
def m(out = STDOUT)
out.puts('hello')
end
# good
$stdout.puts('hello')
hash = { out: $stdout, key: value }
def m(out = $stdout)
out.puts('hello')
end
Use e
instead of ex
. Open
rescue ::JSON::ParserError => ex
- Read upRead up
- Exclude checks
Makes sure that rescued exceptions variables are named as expected.
The PreferredName
config option takes a String
. It represents
the required name of the variable. Its default is e
.
NOTE: This cop does not consider nested rescues because it cannot guarantee that the variable from the outer rescue is not used within the inner rescue (in which case, changing the inner variable would shadow the outer variable).
Example: PreferredName: e (default)
# bad
begin
# do something
rescue MyException => exception
# do something
end
# good
begin
# do something
rescue MyException => e
# do something
end
# good
begin
# do something
rescue MyException => _e
# do something
end
Example: PreferredName: exception
# bad
begin
# do something
rescue MyException => e
# do something
end
# good
begin
# do something
rescue MyException => exception
# do something
end
# good
begin
# do something
rescue MyException => _exception
# do something
end
Call super
to initialize state of the parent class. Open
def initialize(filesystem)
@filesystem = filesystem
@has_begun = false
end
- Read upRead up
- Exclude checks
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.
Example:
# 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
Add empty line after guard clause. Open
return unless $stdout.tty? && !CLI.debug?
- Read upRead up
- Exclude checks
Enforces empty line after guard clause
Example:
# bad
def foo
return if need_return?
bar
end
# good
def foo
return if need_return?
bar
end
# good
def foo
return if something?
return if something_different?
bar
end
# also good
def foo
if something?
do_something
return if need_return?
end
end
Freeze mutable objects assigned to constants. Open
SPEC_ISSUE_ATTRIBUTES = %w[
categories
check_name
content
description
- Read upRead up
- Exclude checks
Checks whether some constant value isn't a mutable literal (e.g. array or hash).
Strict mode can be used to freeze all constants, rather than just literals. Strict mode is considered an experimental feature. It has not been updated with an exhaustive list of all methods that will produce frozen objects so there is a decent chance of getting some false positives. Luckily, there is no harm in freezing an already frozen object.
From Ruby 3.0, this cop honours the magic comment 'shareableconstantvalue'. When this magic comment is set to any acceptable value other than none, it will suppress the offenses raised by this cop. It enforces frozen state.
NOTE: Regexp and Range literals are frozen objects since Ruby 3.0.
NOTE: From Ruby 3.0, interpolated strings are not frozen when
# frozen-string-literal: true
is used, so this cop enforces explicit
freezing for such strings.
NOTE: From Ruby 3.0, this cop allows explicit freezing of constants when
the shareable_constant_value
directive is used.
Safety:
This cop's autocorrection is unsafe since any mutations on objects that
are made frozen will change from being accepted to raising FrozenError
,
and will need to be manually refactored.
Example: EnforcedStyle: literals (default)
# bad
CONST = [1, 2, 3]
# good
CONST = [1, 2, 3].freeze
# good
CONST = <<~TESTING.freeze
This is a heredoc
TESTING
# good
CONST = Something.new
Example: EnforcedStyle: strict
# bad
CONST = Something.new
# bad
CONST = Struct.new do
def foo
puts 1
end
end
# good
CONST = Something.new.freeze
# good
CONST = Struct.new do
def foo
puts 1
end
end.freeze
Example:
# Magic comment - shareable_constant_value: literal
# bad
CONST = [1, 2, 3]
# good
# shareable_constant_value: literal
CONST = [1, 2, 3]
Do not use empty case
condition, instead use an if
expression. Open
case
- Read upRead up
- Exclude checks
Checks for case statements with an empty condition.
Example:
# bad:
case
when x == 0
puts 'x is 0'
when y == 0
puts 'y is 0'
else
puts 'neither is 0'
end
# good:
if x == 0
puts 'x is 0'
elsif y == 0
puts 'y is 0'
else
puts 'neither is 0'
end
# good: (the case condition node is not empty)
case n
when 0
puts 'zero'
when 1
puts 'one'
else
puts 'more'
end
Use e
instead of ex
. Open
rescue Formatters::Formatter::InvalidFormatterError => ex
- Read upRead up
- Exclude checks
Makes sure that rescued exceptions variables are named as expected.
The PreferredName
config option takes a String
. It represents
the required name of the variable. Its default is e
.
NOTE: This cop does not consider nested rescues because it cannot guarantee that the variable from the outer rescue is not used within the inner rescue (in which case, changing the inner variable would shadow the outer variable).
Example: PreferredName: e (default)
# bad
begin
# do something
rescue MyException => exception
# do something
end
# good
begin
# do something
rescue MyException => e
# do something
end
# good
begin
# do something
rescue MyException => _e
# do something
end
Example: PreferredName: exception
# bad
begin
# do something
rescue MyException => e
# do something
end
# good
begin
# do something
rescue MyException => exception
# do something
end
# good
begin
# do something
rescue MyException => _exception
# do something
end
Add empty line after guard clause. Open
end
- Read upRead up
- Exclude checks
Enforces empty line after guard clause
Example:
# bad
def foo
return if need_return?
bar
end
# good
def foo
return if need_return?
bar
end
# good
def foo
return if something?
return if something_different?
bar
end
# also good
def foo
if something?
do_something
return if need_return?
end
end
ReDoS based DoS vulnerability in Active Support’s underscore Open
activesupport (5.2.8.1)
- Read upRead up
- Exclude checks
Advisory: CVE-2023-22796
URL: https://github.com/rails/rails/releases/tag/v7.0.4.1
Solution: upgrade to >= 5.2.8.15, ~> 5.2.8, >= 6.1.7.1, ~> 6.1.7, >= 7.0.4.1
Use expand_path('VERSION', __dir__)
instead of expand_path('../VERSION', __FILE__)
. Open
VERSION = File.read(File.expand_path("../VERSION", __FILE__))
- Read upRead up
- Exclude checks
Checks for use of the File.expand_path
arguments.
Likewise, it also checks for the Pathname.new
argument.
Contrastive bad case and good case are alternately shown in the following examples.
Example:
# bad
File.expand_path('..', __FILE__)
# good
File.expand_path(__dir__)
# bad
File.expand_path('../..', __FILE__)
# good
File.expand_path('..', __dir__)
# bad
File.expand_path('.', __FILE__)
# good
File.expand_path(__FILE__)
# bad
Pathname(__FILE__).parent.expand_path
# good
Pathname(__dir__).expand_path
# bad
Pathname.new(__FILE__).parent.expand_path
# good
Pathname.new(__dir__).expand_path