Method relationship_save_block
has a Cognitive Complexity of 43 (exceeds 11 allowed). Consider refactoring. Open
def relationship_save_block(relationship_key:, relationship_type: :ems_metadata, parent_type: nil)
lambda do |_ems, inventory_collection|
children_by_parent = Hash.new { |h, k| h[k] = Hash.new { |hh, kk| hh[kk] = [] } }
parent_by_child = Hash.new { |h, k| h[k] = {} }
- Read upRead up
- Create a ticketCreate a ticket
Cognitive Complexity
Cognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.
A method's cognitive complexity is based on a few simple rules:
- Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one
- Code is considered more complex for each "break in the linear flow of the code"
- Code is considered more complex when "flow breaking structures are nested"
Further reading
Cyclomatic complexity for relationship_save_block is too high. [20/11] Open
def relationship_save_block(relationship_key:, relationship_type: :ems_metadata, parent_type: nil)
lambda do |_ems, inventory_collection|
children_by_parent = Hash.new { |h, k| h[k] = Hash.new { |hh, kk| hh[kk] = [] } }
parent_by_child = Hash.new { |h, k| h[k] = {} }
- Read upRead up
- Create a ticketCreate a ticket
- Exclude checks
Checks that the cyclomatic complexity of methods is not higher than the configured maximum. The cyclomatic complexity is the number of linearly independent paths through a method. The algorithm counts decision points and adds one.
An if statement (or unless or ?:) increases the complexity by one. An else branch does not, since it doesn't add a decision point. The && operator (or keyword and) can be converted to a nested if statement, and ||/or is shorthand for a sequence of ifs, so they also add one. Loops can be said to have an exit condition, so they add one. Blocks that are calls to builtin iteration methods (e.g. `ary.map{...}) also add one, others are ignored.
def each_child_node(*types) # count begins: 1
unless block_given? # unless: +1
return to_enum(__method__, *types)
children.each do |child| # each{}: +1
next unless child.is_a?(Node) # unless: +1
yield child if types.empty? || # if: +1, ||: +1
types.include?(child.type)
end
self
end # total: 6
Use collect { |x| x.manager_uuids.to_a }
instead of collect
method chain. Open
manager_uuids = inventory_collection.parent_inventory_collections.collect(&:manager_uuids).map(&:to_a).flatten
- Create a ticketCreate a ticket
- Exclude checks
Use filter_map
instead. Open
vms_and_templates_ids = inventory_collection.data.map { |os| os.vm_or_template&.id }.compact
- Create a ticketCreate a ticket
- Exclude checks
Use collect { |x| x.manager_uuids.to_a }
instead of collect
method chain. Open
manager_uuids = inventory_collection.parent_inventory_collections.collect(&:manager_uuids).map(&:to_a).flatten
- Create a ticketCreate a ticket
- Exclude checks
Do not define constants this way within a block. Open
INVENTORY_RECONNECT_BLOCK = lambda do |inventory_collection, inventory_objects_index, attributes_index|
relation = inventory_collection.model_class.where(:ems_id => nil)
return if relation.count <= 0
- Read upRead up
- Create a ticketCreate a ticket
- Exclude checks
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
.
Example:
# 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
Example: 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