class RuboCop::Cop::ThreadSafety::InstanceVariableInClassMethod

Avoid instance variables in class methods.

@example

# bad
class User
  def self.notify(info)
    @info = validate(info)
    Notifier.new(@info).deliver
  end
end

class Model
  class << self
    def table_name(name)
      @table_name = name
    end
  end
end

class Host
  %i[uri port].each do |key|
    define_singleton_method("#{key}=") do |value|
      instance_variable_set("@#{key}", value)
    end
  end
end

module Example
  module ClassMethods
    def test(params)
      @params = params
    end
  end
end

Constants

MSG

Public Instance Methods

on_ivar(node) click to toggle source
# File lib/rubocop/cop/thread_safety/instance_variable_in_class_method.rb, line 51
def on_ivar(node)
  return unless class_method_definition?(node)
  return if synchronized?(node)

  add_offense(node, location: :name, message: MSG)
end
Also aliased as: on_ivasgn
on_ivasgn(node)
Alias for: on_ivar
on_send(node) click to toggle source
# File lib/rubocop/cop/thread_safety/instance_variable_in_class_method.rb, line 59
def on_send(node)
  return unless instance_variable_call?(node)
  return unless class_method_definition?(node)
  return if synchronized?(node)

  add_offense(node, message: MSG)
end

Private Instance Methods

class_method_definition?(node) click to toggle source
# File lib/rubocop/cop/thread_safety/instance_variable_in_class_method.rb, line 69
def class_method_definition?(node)
  in_defs?(node) ||
    in_def_sclass?(node) ||
    in_def_class_methods?(node) ||
    singleton_method_definition?(node)
end
in_def_class_methods?(node) click to toggle source
# File lib/rubocop/cop/thread_safety/instance_variable_in_class_method.rb, line 92
def in_def_class_methods?(node)
  defn = node.ancestors.find(&:def_type?)
  return unless defn

  mod = defn.ancestors.find do |ancestor|
    %i[class module].include?(ancestor.type)
  end
  return unless mod

  class_methods_module?(mod)
end
in_def_sclass?(node) click to toggle source
# File lib/rubocop/cop/thread_safety/instance_variable_in_class_method.rb, line 82
def in_def_sclass?(node)
  defn = node.ancestors.find do |ancestor|
    ancestor.type == :def
  end

  defn&.ancestors&.any? do |ancestor|
    ancestor.type == :sclass
  end
end
in_defs?(node) click to toggle source
# File lib/rubocop/cop/thread_safety/instance_variable_in_class_method.rb, line 76
def in_defs?(node)
  node.ancestors.any? do |ancestor|
    ancestor.type == :defs
  end
end
instance_variable_call?(node) click to toggle source
# File lib/rubocop/cop/thread_safety/instance_variable_in_class_method.rb, line 121
def instance_variable_call?(node)
  instance_variable_set_call?(node) || instance_variable_get_call?(node)
end
singleton_method_definition?(node) click to toggle source
# File lib/rubocop/cop/thread_safety/instance_variable_in_class_method.rb, line 104
def singleton_method_definition?(node)
  node.ancestors.any? do |ancestor|
    next unless ancestor.children.first.is_a? AST::SendNode

    ancestor.children.first.command? :define_singleton_method
  end
end
synchronized?(node) click to toggle source
# File lib/rubocop/cop/thread_safety/instance_variable_in_class_method.rb, line 112
def synchronized?(node)
  node.ancestors.find do |ancestor|
    next unless ancestor.block_type?

    s = ancestor.children.first
    s.send_type? && s.children.last == :synchronize
  end
end