class RuboCop::Cop::Style::RedundantFetchBlock

Identifies places where ‘fetch(key) { value }` can be replaced by `fetch(key, value)`.

In such cases ‘fetch(key, value)` method is faster than `fetch(key) { value }`.

@safety

This cop is unsafe because it cannot be guaranteed that the receiver
does not have a different implementation of `fetch`.

@example SafeForConstants: false (default)

# bad
hash.fetch(:key) { 5 }
hash.fetch(:key) { true }
hash.fetch(:key) { nil }
array.fetch(5) { :value }
ENV.fetch(:key) { 'value' }

# good
hash.fetch(:key, 5)
hash.fetch(:key, true)
hash.fetch(:key, nil)
array.fetch(5, :value)
ENV.fetch(:key, 'value')

@example SafeForConstants: true

# bad
ENV.fetch(:key) { VALUE }

# good
ENV.fetch(:key, VALUE)

Constants

MSG

Public Instance Methods

on_block(node) click to toggle source
# File lib/rubocop/cop/style/redundant_fetch_block.rb, line 53
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
  redundant_fetch_block_candidate?(node) do |send, body|
    return if should_not_check?(send, body)

    range = fetch_range(send, node)
    good = build_good_method(send, body)
    bad = build_bad_method(send, body)

    add_offense(range, message: format(MSG, good: good, bad: bad)) do |corrector|
      receiver, _, key = send.children
      default_value = body ? body.source : 'nil'

      corrector.replace(node, "#{receiver.source}.fetch(#{key.source}, #{default_value})")
    end
  end
end

Private Instance Methods

basic_literal?(node) click to toggle source
# File lib/rubocop/cop/style/redundant_fetch_block.rb, line 72
def basic_literal?(node)
  node&.basic_literal?
end
build_bad_method(send, body) click to toggle source
# File lib/rubocop/cop/style/redundant_fetch_block.rb, line 102
def build_bad_method(send, body)
  key = send.children[2].source
  block = body ? "{ #{body.source} }" : '{}'

  "fetch(#{key}) #{block}"
end
build_good_method(send, body) click to toggle source
# File lib/rubocop/cop/style/redundant_fetch_block.rb, line 95
def build_good_method(send, body)
  key = send.children[2].source
  default_value = body ? body.source : 'nil'

  "fetch(#{key}, #{default_value})"
end
check_for_constant?() click to toggle source
# File lib/rubocop/cop/style/redundant_fetch_block.rb, line 109
def check_for_constant?
  cop_config['SafeForConstants']
end
check_for_string?() click to toggle source
# File lib/rubocop/cop/style/redundant_fetch_block.rb, line 113
def check_for_string?
  frozen_string_literals_enabled?
end
const_type?(node) click to toggle source
# File lib/rubocop/cop/style/redundant_fetch_block.rb, line 76
def const_type?(node)
  node&.const_type?
end
fetch_range(send, node) click to toggle source
# File lib/rubocop/cop/style/redundant_fetch_block.rb, line 91
def fetch_range(send, node)
  range_between(send.loc.selector.begin_pos, node.loc.end.end_pos)
end
should_not_check?(send, body) click to toggle source
# File lib/rubocop/cop/style/redundant_fetch_block.rb, line 80
def should_not_check?(send, body)
  (body&.const_type? && !check_for_constant?) ||
    (body&.str_type? && !check_for_string?) ||
    rails_cache?(send.receiver)
end