Class: RuboCop::Cop::ViewComponent::NoGlobalState

Inherits:
Base
  • Object
show all
Includes:
Base
Defined in:
lib/rubocop/cop/view_component/no_global_state.rb

Overview

Prevents direct access to global state within ViewComponent classes.

ViewComponent’s own documentation notes that accessing ‘request` directly “introduces coupling that inhibits encapsulation & reuse, often making testing difficult.” The same principle applies to `params`, `session`, `cookies`, and `flash`.

Examples:

# bad
class UserComponent < ViewComponent::Base
  def admin?
    params[:admin]
  end
end

# good
class UserComponent < ViewComponent::Base
  def initialize(admin:)
    @admin = admin
  end

  def admin?
    @admin
  end
end

Constant Summary collapse

MSG =
"Avoid accessing `%<method>s` directly in ViewComponents. " \
"Pass necessary data through the constructor instead."
GLOBAL_STATE_METHODS =
%i[
  params
  request
  session
  cookies
  flash
].freeze
RESTRICT_ON_SEND =
GLOBAL_STATE_METHODS

Instance Method Summary collapse

Methods included from Base

#component_namespaces, #enclosing_class, #fully_qualified_name, #inside_view_component?, #view_component_class?, #view_component_parent?, #view_component_parent_class?

Instance Method Details

#global_state_access?(node) ⇒ Object



49
50
51
# File 'lib/rubocop/cop/view_component/no_global_state.rb', line 49

def_node_matcher :global_state_access?, <<~PATTERN
  (send nil? ${:params :request :session :cookies :flash} ...)
PATTERN

#on_send(node) ⇒ Object Also known as: on_csend



58
59
60
61
62
63
64
65
66
# File 'lib/rubocop/cop/view_component/no_global_state.rb', line 58

def on_send(node)
  return unless inside_view_component?(node)

  method_name = global_state_access?(node)
  return unless method_name
  return if sorbet_signature?(node)

  add_offense(node, message: format(MSG, method: method_name))
end

#sorbet_sig_block?(node) ⇒ Object



54
55
56
# File 'lib/rubocop/cop/view_component/no_global_state.rb', line 54

def_node_matcher :sorbet_sig_block?, <<~PATTERN
  (block (send nil? :sig) ...)
PATTERN