class RuboCop::Cop::Style::FetchEnvVar
Suggests ‘ENV.fetch` for the replacement of `ENV[]`. `ENV[]` silently fails and returns `nil` when the environment variable is unset, which may cause unexpected behaviors when the developer forgets to set it. On the other hand, `ENV.fetch` raises `KeyError` or returns the explicitly specified default value.
@example DefaultToNil: true (default)
# bad ENV['X'] x = ENV['X'] # good ENV.fetch('X', nil) x = ENV.fetch('X', nil) # also good !ENV['X'] ENV['X'].some_method # (e.g. `.nil?`)
@example DefaultToNil: false
# bad ENV['X'] x = ENV['X'] # good ENV.fetch('X') x = ENV.fetch('X') # also good !ENV['X'] ENV['X'].some_method # (e.g. `.nil?`)
Constants
- MSG_WITHOUT_NIL
- MSG_WITH_NIL
- RESTRICT_ON_SEND
Public Instance Methods
Source
# File lib/rubocop/cop/style/fetch_env_var.rb, line 50 def on_send(node) env_with_bracket?(node) do |name_node| break unless offensive?(node) message = format(offense_message, key: name_node.source) add_offense(node, message: message) do |corrector| corrector.replace(node, new_code(name_node)) end end end
Private Instance Methods
Source
# File lib/rubocop/cop/style/fetch_env_var.rb, line 128 def allowable_use?(node) used_as_flag?(node) || message_chained_with_dot?(node) || assigned?(node) || or_lhs?(node) end
The following are allowed cases:
Source
# File lib/rubocop/cop/style/fetch_env_var.rb, line 71 def allowed_var?(node) env_key_node = node.children.last env_key_node.str_type? && cop_config['AllowedVars'].include?(env_key_node.value) end
Source
# File lib/rubocop/cop/style/fetch_env_var.rb, line 136 def assigned?(node) return false unless (parent = node.parent)&.assignment? lhs, _method, _rhs = *parent node == lhs end
The following are allowed cases:
Source
# File lib/rubocop/cop/style/fetch_env_var.rb, line 63 def default_to_nil? cop_config.fetch('DefaultToNil', true) end
Source
# File lib/rubocop/cop/style/fetch_env_var.rb, line 112 def message_chained_with_dot?(node) return false if node.root? parent = node.parent return false if !parent.call_type? || parent.children.first != node parent.dot? || parent.safe_navigation? end
Check if the node is a receiver and receives a message with dot syntax.
Source
# File lib/rubocop/cop/style/fetch_env_var.rb, line 149 def new_code(name_node) if default_to_nil? "ENV.fetch(#{name_node.source}, nil)" else "ENV.fetch(#{name_node.source})" end end
Source
# File lib/rubocop/cop/style/fetch_env_var.rb, line 67 def offense_message default_to_nil? ? MSG_WITH_NIL : MSG_WITHOUT_NIL end
Source
# File lib/rubocop/cop/style/fetch_env_var.rb, line 107 def offensive?(node) !(allowed_var?(node) || allowable_use?(node)) end
Source
# File lib/rubocop/cop/style/fetch_env_var.rb, line 143 def or_lhs?(node) return false unless (parent = node.parent)&.or_type? parent.lhs == node || parent.parent&.or_type? end
Source
Source
# File lib/rubocop/cop/style/fetch_env_var.rb, line 76 def used_as_flag?(node) return false if node.root? return true if used_if_condition_in_body?(node) node.parent.send_type? && (node.parent.prefix_bang? || node.parent.comparison_method?) end
Source
# File lib/rubocop/cop/style/fetch_env_var.rb, line 83 def used_if_condition_in_body?(node) if_node = node.ancestors.find(&:if_type?) return false unless (condition = if_node&.condition) return true if condition.send_type? && (condition.child_nodes == node.child_nodes) used_in_condition?(node, condition) end
Source
# File lib/rubocop/cop/style/fetch_env_var.rb, line 92 def used_in_condition?(node, condition) if condition.send_type? return true if condition.assignment_method? && partial_matched?(node, condition) return false if !condition.comparison_method? && !condition.predicate_method? end condition.child_nodes.any?(node) end