Showing 1,313 of 1,313 total issues
Redundant safe navigation detected. Open
export_attributes['filter'] = MiqExpression.new(export_attributes["filter"].exp) if export_attributes["filter"]&.kind_of?(MiqExpression)
- Read upRead up
- Create a ticketCreate a ticket
- Exclude checks
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.
The AllowedMethods
option specifies nil-safe methods,
in other words, it is a method that is allowed to skip safe navigation.
Note that the AllowedMethod
option is not an option that specifies methods
for which to suppress (allow) this cop's check.
In the example below, the safe navigation operator (&.
) is unnecessary
because NilClass
has methods like respond_to?
and is_a?
.
Safety:
This cop is unsafe, because autocorrection can change the return type of
the expression. An offending expression that previously could return nil
will be autocorrected to never return nil
.
Example:
# 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)
Example: AllowedMethods: [nilsafemethod]
# bad
do_something if attrs&.nil_safe_method(:[])
# good
do_something if attrs.nil_safe_method(:[])
do_something if attrs&.not_nil_safe_method(:[])
Avoid rescuing the Exception
class. Perhaps you meant to rescue StandardError
? Open
rescue Exception => err
_log.log_backtrace(err)
- Read upRead up
- Create a ticketCreate a ticket
- Exclude checks
Checks for rescue
blocks targeting the Exception class.
Example:
# bad
begin
do_something
rescue Exception
handle_exception
end
Example:
# good
begin
do_something
rescue ArgumentError
handle_exception
end
Use filter_map
instead. Open
@cloud_subnets_names ||= cloud_subnets.collect(&:name).compact.uniq
- Create a ticketCreate a ticket
- Exclude checks
Use filter_map
instead. Open
result = image.customization_templates.collect do |c|
# filter customizationtemplates
if c.pxe_image_type.provision_type.blank? || c.pxe_image_type.provision_type == prov_typ
@values[:customization_template_script] = c.script if c.id == customization_template_id
build_ci_hash_struct(c, [:name, :description, :updated_at])
- Create a ticketCreate a ticket
- Exclude checks
Prefer using YAML.safe_load
over YAML.load
. Open
ost.args[1] = YAML.load(ost.args[1]) # TODO: YAML.dump'd in call_scan - need it be?
- Read upRead up
- Create a ticketCreate a ticket
- Exclude checks
Checks for the use of YAML class methods which have potential security issues leading to remote code execution when loading from an untrusted source.
NOTE: Ruby 3.1+ (Psych 4) uses Psych.load
as Psych.safe_load
by default.
Safety:
The behavior of the code might change depending on what was
in the YAML payload, since YAML.safe_load
is more restrictive.
Example:
# bad
YAML.load("--- !ruby/object:Foo {}") # Psych 3 is unsafe by default
# good
YAML.safe_load("--- !ruby/object:Foo {}", [Foo]) # Ruby 2.5 (Psych 3)
YAML.safe_load("--- !ruby/object:Foo {}", permitted_classes: [Foo]) # Ruby 3.0- (Psych 3)
YAML.load("--- !ruby/object:Foo {}", permitted_classes: [Foo]) # Ruby 3.1+ (Psych 4)
YAML.dump(foo)
Avoid more than 3 levels of block nesting. Open
rescue => err
_log.warn("#{err.message}, unable to raise policy event: [vm_scan_complete]")
- Read upRead up
- Create a ticketCreate a ticket
- Exclude checks
Checks for excessive nesting of conditional and looping constructs.
You can configure if blocks are considered using the CountBlocks
option. When set to false
(the default) blocks are not counted
towards the nesting level. Set to true
to count blocks as well.
The maximum level of nesting allowed is configurable.
Do not suppress exceptions. Open
rescue
- Read upRead up
- Create a ticketCreate a ticket
- Exclude checks
Checks for rescue
blocks with no body.
Example:
# 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
Example: AllowComments: true (default)
# good
def some_method
do_something
rescue
# do nothing
end
# good
begin
do_something
rescue
# do nothing
end
Example: AllowComments: false
# bad
def some_method
do_something
rescue
# do nothing
end
# bad
begin
do_something
rescue
# do nothing
end
Example: 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
Example: AllowNil: false
# bad
def some_method
do_something
rescue
nil
end
# bad
begin
do_something
rescue
nil
end
# bad
do_something rescue nil
Script file copy_reports_structure.rb doesn't have execute permission. Open
#!/usr/bin/env ruby
- Read upRead up
- Create a ticketCreate a ticket
- Exclude checks
Checks if a file which has a shebang line as its first line is granted execute permission.
Example:
# 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'
Avoid immutable Array literals in loops. It is better to extract it into a local variable or a constant. Open
[:ae_namespaces, :ae_classes, :ae_instances, :ae_methods].each do |meth|
- Create a ticketCreate a ticket
- Exclude checks
Use atomic file operation method FileUtils.rm_f
. Open
File.delete(yml_fname) if File.exist?(yml_fname)
- Read upRead up
- Create a ticketCreate a ticket
- Exclude checks
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.
Example:
# bad - race condition with another process may result in an error in `mkdir`
unless Dir.exist?(path)
FileUtils.mkdir(path)
end
# good - atomic and idempotent creation
FileUtils.mkdir_p(path)
# bad - race condition with another process may result in an error in `remove`
if File.exist?(path)
FileUtils.remove(path)
end
# good - atomic and idempotent removal
FileUtils.rm_f(path)
Prefer using YAML.safe_load
over YAML.load
. Open
hash = old_value.kind_of?(Hash) ? old_value : YAML.load(old_value)
- Read upRead up
- Create a ticketCreate a ticket
- Exclude checks
Checks for the use of YAML class methods which have potential security issues leading to remote code execution when loading from an untrusted source.
NOTE: Ruby 3.1+ (Psych 4) uses Psych.load
as Psych.safe_load
by default.
Safety:
The behavior of the code might change depending on what was
in the YAML payload, since YAML.safe_load
is more restrictive.
Example:
# bad
YAML.load("--- !ruby/object:Foo {}") # Psych 3 is unsafe by default
# good
YAML.safe_load("--- !ruby/object:Foo {}", [Foo]) # Ruby 2.5 (Psych 3)
YAML.safe_load("--- !ruby/object:Foo {}", permitted_classes: [Foo]) # Ruby 3.0- (Psych 3)
YAML.load("--- !ruby/object:Foo {}", permitted_classes: [Foo]) # Ruby 3.1+ (Psych 4)
YAML.dump(foo)
Use ==
if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition. Open
elsif match = line[/Processing\sby\s([\d\w:.\#_-]*)/, 1]
- Read upRead up
- Create a ticketCreate a ticket
- Exclude checks
Checks for assignments in the conditions of if/while/until.
AllowSafeAssignment
option for safe assignment.
By safe assignment we mean putting parentheses around
an assignment to indicate "I know I'm using an assignment
as a condition. It's not a mistake."
Safety:
This cop's autocorrection is unsafe because it assumes that the author meant to use an assignment result as a condition.
Example:
# bad
if some_var = true
do_something
end
# good
if some_var == true
do_something
end
Example: AllowSafeAssignment: true (default)
# good
if (some_var = true)
do_something
end
Example: AllowSafeAssignment: false
# bad
if (some_var = true)
do_something
end
Use count
instead of select...count
. Open
duplicate_hosts = hosts_index.select { |_by, hosts| hosts.count == 2 && hosts.select(&:has_active_ems?).count == 1 }
- Read upRead up
- Create a ticketCreate a ticket
- Exclude checks
This cop is used to identify usages of count
on an Enumerable
that
follow calls to select
or reject
. Querying logic can instead be
passed to the count
call.
Example:
# bad
[1, 2, 3].select { |e| e > 2 }.size
[1, 2, 3].reject { |e| e > 2 }.size
[1, 2, 3].select { |e| e > 2 }.length
[1, 2, 3].reject { |e| e > 2 }.length
[1, 2, 3].select { |e| e > 2 }.count { |e| e.odd? }
[1, 2, 3].reject { |e| e > 2 }.count { |e| e.even? }
array.select(&:value).count
# good
[1, 2, 3].count { |e| e > 2 }
[1, 2, 3].count { |e| e < 2 }
[1, 2, 3].count { |e| e > 2 && e.odd? }
[1, 2, 3].count { |e| e < 2 && e.even? }
Model.select('field AS field_one').count
Model.select(:value).count
ActiveRecord
compatibility:
ActiveRecord
will ignore the block that is passed to count
.
Other methods, such as select
, will convert the association to an
array and then run the block on the array. A simple work around to
make count
work with a block is to call to_a.count {...}
.
Example: Model.where(id: [1, 2, 3].select { |m| m.method == true }.size
becomes:
Model.where(id: [1, 2, 3]).to_a.count { |m| m.method == true }
Wrap expressions with varying precedence with parentheses to avoid ambiguity. Open
tag_val1 = tag_val + " " * (@line_len - tag_val.length - 2)
- Read upRead up
- Create a ticketCreate a ticket
- Exclude checks
Looks for expressions containing multiple binary operators
where precedence is ambiguous due to lack of parentheses. For example,
in 1 + 2 * 3
, the multiplication will happen before the addition, but
lexically it appears that the addition will happen first.
The cop does not consider unary operators (ie. !a
or -b
) or comparison
operators (ie. a =~ b
) because those are not ambiguous.
NOTE: Ranges are handled by Lint/AmbiguousRange
.
Example:
# 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
Duplicate branch body detected. Open
elsif ["<drift>"].include?(mri.db) && r[0] == "Changed:"
line_wrapper = true # Wrap drift changed lines with header rows
- Read upRead up
- Create a ticketCreate a ticket
- Exclude checks
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.
Example:
# 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
Example: IgnoreLiteralBranches: true
# good
case size
when "small" then 100
when "medium" then 250
when "large" then 1000
else 250
end
Example: IgnoreConstantBranches: true
# good
case size
when "small" then SMALL_SIZE
when "medium" then MEDIUM_SIZE
when "large" then LARGE_SIZE
else MEDIUM_SIZE
end
Avoid immutable Array literals in loops. It is better to extract it into a local variable or a constant. Open
next unless %w[websocket_closed ticket_invalid].include?(console.proxy_status)
- Create a ticketCreate a ticket
- Exclude checks
Use filter_map
instead. Open
value - tenant.children.includes(:tenant_quotas).map do |c|
cq = c.tenant_quotas.send(name).take
cq.value if cq
end.compact.sum - used
- Create a ticketCreate a ticket
- Exclude checks
Use filter_map
instead. Open
perfs.collect(&:abs_max_cpu_usagemhz_rate_average_value).compact.max
- Create a ticketCreate a ticket
- Exclude checks
Remove unnecessary existence check File.exist?
. Open
File.delete(yml_fname) if File.exist?(yml_fname)
- Read upRead up
- Create a ticketCreate a ticket
- Exclude checks
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.
Example:
# bad - race condition with another process may result in an error in `mkdir`
unless Dir.exist?(path)
FileUtils.mkdir(path)
end
# good - atomic and idempotent creation
FileUtils.mkdir_p(path)
# bad - race condition with another process may result in an error in `remove`
if File.exist?(path)
FileUtils.remove(path)
end
# good - atomic and idempotent removal
FileUtils.rm_f(path)
Use Array.new(10)
with a block instead of .times.map
. Open
avg = 10.times.map { Benchmark.realtime { client.get("test") } }.inject(:+) / 10.0
- Read upRead up
- Create a ticketCreate a ticket
- Exclude checks
This cop checks for .times.map calls. In most cases such calls can be replaced with an explicit array creation.
Example:
# bad
9.times.map do |i|
i.to_s
end
# good
Array.new(9) do |i|
i.to_s
end