class RuboCop::Cop::Style::RedundantFetchBlock
ENV.fetch(:key, VALUE)
# good
ENV.fetch(:key) { VALUE }
# bad
@example SafeForConstants: true
ENV.fetch(:key, ‘value’)
array.fetch(5, :value)
hash.fetch(:key, nil)
hash.fetch(:key, true)
hash.fetch(:key, 5)
# good
ENV.fetch(:key) { ‘value’ }
array.fetch(5) { :value }
hash.fetch(:key) { nil }
hash.fetch(:key) { true }
hash.fetch(:key) { 5 }
# bad
@example SafeForConstants: false (default)
does not have a different implementation of ‘fetch`.
This cop is unsafe because it cannot be guaranteed that the receiver
@safety
but not when disabled.
when frozen string literal magic comment is enabled (i.e. `# frozen_string_literal: true`),
NOTE: The block string `’value’‘ in `hash.fetch(:key) { ’value’ }‘ is detected
In such cases `fetch(key, value)` method is faster than `fetch(key) { value }`.
Identifies places where `fetch(key) { value }` can be replaced by `fetch(key, value)`.
def basic_literal?(node)
def basic_literal?(node) node&.basic_literal? end
def build_bad_method(send, body)
def build_bad_method(send, body) key = send.children[2].source block = body ? "{ #{body.source} }" : '{}' "fetch(#{key}) #{block}" end
def build_good_method(send, body)
def build_good_method(send, body) key = send.children[2].source default_value = body ? body.source : 'nil' "fetch(#{key}, #{default_value})" end
def check_for_constant?
def check_for_constant? cop_config['SafeForConstants'] end
def check_for_string?
def check_for_string? frozen_string_literals_enabled? end
def const_type?(node)
def const_type?(node) node&.const_type? end
def fetch_range(send, node)
def fetch_range(send, node) range_between(send.loc.selector.begin_pos, node.loc.end.end_pos) end
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
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
def should_not_check?(send, body)
def should_not_check?(send, body) (body&.const_type? && !check_for_constant?) || (body&.str_type? && !check_for_string?) || rails_cache?(send.receiver) end