Spec-Zone.ru › Ruby on Rails 7.0

class Module

Parent:
Object
Included modules:
Module::Concerning

Доступ к атрибутам

Расширяет объект модуля с помощью доступа к атрибутам класса/модуля и экземпляра, как и встроенные accessors attr* для атрибутов экземпляра.

Доступ к атрибутам на основе потока

Расширяет объект модуля с помощью доступа к атрибутам класса/модуля и экземпляра, как и встроенные accessors attr* для атрибутов экземпляра, но делает это на основе каждого потока.

Таким образом, значения ограничены пространством Thread.current под именем класса модуля.

Обратите внимание, что они также могут быть ограничены по волокну, если Rails.application.config.active_support.isolation_level задано как `:fiber`

Константы

DELEGATION_RESERVED_KEYWORDS
DELEGATION_RESERVED_METHOD_NAMES
RUBY_RESERVED_KEYWORDS

Атрибуты

attr_internal_naming_format[RW]

Общедоступные методы экземпляров

alias_attribute(new_name, old_name) Показать исходный код
# File activesupport/lib/active_support/core_ext/module/aliasing.rb, line 21
  def alias_attribute(new_name, old_name)
    # The following reader methods use an explicit `self` receiver in order to
    # support aliases that start with an uppercase letter. Otherwise, they would
    # be resolved as constants instead.
    module_eval <<-STR, __FILE__, __LINE__ + 1
      def #{new_name}; self.#{old_name}; end          # def subject; self.title; end
      def #{new_name}?; self.#{old_name}?; end        # def subject?; self.title?; end
      def #{new_name}=(v); self.#{old_name} = v; end  # def subject=(v); self.title = v; end
    STR
  end

Позволяет создавать псевдонимы для атрибутов, включая геттер, сеттер и предикат.

class Content < ActiveRecord::Base
  # has a title attribute
end

class Email < Content
  alias_attribute :subject, :title
end

e = Email.find(1)
e.title    # => "Superstars"
e.subject  # => "Superstars"
e.subject? # => true
e.subject = "Megastars"
e.title    # => "Megastars"
anonymous?() Показать исходный код
# File activesupport/lib/active_support/core_ext/module/anonymous.rb, line 27
def anonymous?
  name.nil?
end

Модуль может или не может иметь имя.

module M; end
M.name # => "M"

m = Module.new
m.name # => nil

anonymous? метод возвращает true, если модуль не имеет имени, и false в противном случае:

Module.new.anonymous? # => true

module M; end
M.anonymous?          # => false

Модуль получает имя при первом присваивании его константе. Либо с помощью ключевого слова module или class или явного присваивания:

m = Module.new # creates an anonymous module
m.anonymous?   # => true
M = m          # m gets a name here as a side-effect
m.name         # => "M"
m.anonymous?   # => false
attr_internal(*attrs)
Псевдоним для: attr_internal_accessor
attr_internal_accessor(*attrs) Показать исходный код
# File activesupport/lib/active_support/core_ext/module/attr_internal.rb, line 16
def attr_internal_accessor(*attrs)
  attr_internal_reader(*attrs)
  attr_internal_writer(*attrs)
end

Объявляет чтение и запись атрибута, поддерживаемого внутренне именованной переменной экземпляра.

Также псевдоним для: attr_internal
attr_internal_reader(*attrs) Показать исходный код
# File activesupport/lib/active_support/core_ext/module/attr_internal.rb, line 5
def attr_internal_reader(*attrs)
  attrs.each { |attr_name| attr_internal_define(attr_name, :reader) }
end

Объявляет чтение атрибута, поддерживаемого внутренне именованной переменной экземпляра.

attr_internal_writer(*attrs) Показать исходный код
# File activesupport/lib/active_support/core_ext/module/attr_internal.rb, line 10
def attr_internal_writer(*attrs)
  attrs.each { |attr_name| attr_internal_define(attr_name, :writer) }
end

Объявляет запись атрибута, поддерживаемого внутренне именованной переменной экземпляра.

cattr_accessor(*syms, instance_reader: true, instance_writer: true, instance_accessor: true, default: nil, &blk)
Псевдоним для: mattr_accessor
cattr_reader(*syms, instance_reader: true, instance_accessor: true, default: nil, location: nil)
Псевдоним для: mattr_reader
cattr_writer(*syms, instance_writer: true, instance_accessor: true, default: nil, location: nil)
Псевдоним для: mattr_writer
delegate(*methods, to: nil, prefix: nil, allow_nil: nil, private: nil) Показать исходный код
# File activesupport/lib/active_support/core_ext/module/delegation.rb, line 171
def delegate(*methods, to: nil, prefix: nil, allow_nil: nil, private: nil)
  unless to
    raise ArgumentError, "Delegation needs a target. Supply a keyword argument 'to' (e.g. delegate :hello, to: :greeter)."
  end

  if prefix == true && /^[^a-z_]/.match?(to)
    raise ArgumentError, "Can only automatically set the delegation prefix when delegating to a method."
  end

  method_prefix = \
    if prefix
      "#{prefix == true ? to : prefix}_"
    else
      ""
    end

  location = caller_locations(1, 1).first
  file, line = location.path, location.lineno

  to = to.to_s
  to = "self.#{to}" if DELEGATION_RESERVED_METHOD_NAMES.include?(to)

  method_def = []
  method_names = []

  methods.map do |method|
    method_name = prefix ? "#{method_prefix}#{method}" : method
    method_names << method_name.to_sym

    # Attribute writer methods only accept one argument. Makes sure []=
    # methods still accept two arguments.
    definition = /[^\]]=\z/.match?(method) ? "arg" : "..."

    # The following generated method calls the target exactly once, storing
    # the returned value in a dummy variable.
    #
    # Reason is twofold: On one hand doing less calls is in general better.
    # On the other hand it could be that the target has side-effects,
    # whereas conceptually, from the user point of view, the delegator should
    # be doing one call.
    if allow_nil
      method = method.to_s

      method_def <<
        "def #{method_name}(#{definition})" <<
        "  _ = #{to}" <<
        "  if !_.nil? || nil.respond_to?(:#{method})" <<
        "    _.#{method}(#{definition})" <<
        "  end" <<
        "end"
    else
      method = method.to_s
      method_name = method_name.to_s

      method_def <<
        "def #{method_name}(#{definition})" <<
        "  _ = #{to}" <<
        "  _.#{method}(#{definition})" <<
        "rescue NoMethodError => e" <<
        "  if _.nil? && e.name == :#{method}" <<
        %(   raise DelegationError, "#{self}##{method_name} delegated to #{to}.#{method}, but #{to} is nil: \#{self.inspect}") <<
        "  else" <<
        "    raise" <<
        "  end" <<
        "end"
    end
  end
  module_eval(method_def.join(";"), file, line)
  private(*method_names) if private
  method_names
end

Предоставляет метод delegate класса для удобного экспонирования общедоступных методов содержащихся объектов в качестве ваших собственных.

Параметры

  • :to — Указывает имя целевого объекта в виде символа или строки

  • :prefix — Добавляет префикс к новому методу с именем целевого объекта или пользовательским префиксом

  • :allow_nil — Если true, предотвращает возникновение Module::DelegationError

  • :private — Если true, изменяет видимость метода на private

Макрокоманда получает одно или несколько имён методов (указанных как символы или строки) и имя целевого объекта через параметр :to (также символ или строка).

Делегирование особенно полезно с ассоциациями Active Record:

class Greeter < ActiveRecord::Base
  def hello
    'hello'
  end

  def goodbye
    'goodbye'
  end
end

class Foo < ActiveRecord::Base
  belongs_to :greeter
  delegate :hello, to: :greeter
end

Foo.new.hello   # => "hello"
Foo.new.goodbye # => NoMethodError: undefined method `goodbye' for #<Foo:0x1af30c>

Разрешено несколько делегатов на один и тот же объект:

class Foo < ActiveRecord::Base
  belongs_to :greeter
  delegate :hello, :goodbye, to: :greeter
end

Foo.new.goodbye # => "goodbye"

Методы могут быть делегированы переменным экземпляра, класса или константам, указав их в виде символов:

class Foo
  CONSTANT_ARRAY = [0,1,2,3]
  @@class_array  = [4,5,6,7]

  def initialize
    @instance_array = [8,9,10,11]
  end
  delegate :sum, to: :CONSTANT_ARRAY
  delegate :min, to: :@@class_array
  delegate :max, to: :@instance_array
end

Foo.new.sum # => 6
Foo.new.min # => 4
Foo.new.max # => 11

Также можно делегировать метод классу, используя :class:

class Foo
  def self.hello
    "world"
  end

  delegate :hello, to: :class
end

Foo.new.hello # => "world"

Делегаты могут быть дополнительно префиксрованы с помощью параметра :prefix. Если значение true, методы делегата префиксруются именем делегируемого объекта.

Person = Struct.new(:name, :address)

class Invoice < Struct.new(:client)
  delegate :name, :address, to: :client, prefix: true
end

john_doe = Person.new('John Doe', 'Vimmersvej 13')
invoice = Invoice.new(john_doe)
invoice.client_name    # => "John Doe"
invoice.client_address # => "Vimmersvej 13"

Также можно указать произвольный префикс.

class Invoice < Struct.new(:client)
  delegate :name, :address, to: :client, prefix: :customer
end

invoice = Invoice.new(john_doe)
invoice.customer_name    # => 'John Doe'
invoice.customer_address # => 'Vimmersvej 13'

Методы по умолчанию являются public. Передайте private: true, чтобы изменить это.

class User < ActiveRecord::Base
  has_one :profile
  delegate :first_name, to: :profile
  delegate :date_of_birth, to: :profile, private: true

  def age
    Date.today.year - date_of_birth.year
  end
end

User.new.first_name # => "Tomas"
User.new.date_of_birth # => NoMethodError: private method `date_of_birth' called for #<User:0x00000008221340>
User.new.age # => 2

Если целевой объект nil и не отвечает на делегированный метод, возникает Module::DelegationError. Если вы хотите вместо этого вернуть nil, используйте параметр :allow_nil

class User < ActiveRecord::Base
  has_one :profile
  delegate :age, to: :profile
end

User.new.age
# => Module::DelegationError: User#age delegated to profile.age, but profile is nil

Но если отсутствие профиля приемлемо и не должно быть ошибкой:

class User < ActiveRecord::Base
  has_one :profile
  delegate :age, to: :profile, allow_nil: true
end

User.new.age # nil

Обратите внимание, что если целевой объект не nil, вызов будет выполнен независимо от параметра :allow_nil, и, следовательно, исключение всё равно будет вызвано, если объект не отвечает на метод:

class Foo
  def initialize(bar)
    @bar = bar
  end

  delegate :name, to: :@bar, allow_nil: true
end

Foo.new("Bar").name # raises NoMethodError: undefined method `name'

Целевой метод должен быть public, в противном случае будет вызвано NoMethodError.

delegate_missing_to(target, allow_nil: nil) Показать исходный код
# File activesupport/lib/active_support/core_ext/module/delegation.rb, line 289
  def delegate_missing_to(target, allow_nil: nil)
    target = target.to_s
    target = "self.#{target}" if DELEGATION_RESERVED_METHOD_NAMES.include?(target)

    module_eval <<-RUBY, __FILE__, __LINE__ + 1
      def respond_to_missing?(name, include_private = false)
        # It may look like an oversight, but we deliberately do not pass
        # +include_private+, because they do not get delegated.

        return false if name == :marshal_dump || name == :_dump
        #{target}.respond_to?(name) || super
      end

      def method_missing(method, *args, &block)
        if #{target}.respond_to?(method)
          #{target}.public_send(method, *args, &block)
        else
          begin
            super
          rescue NoMethodError
            if #{target}.nil?
              if #{allow_nil == true}
                nil
              else
                raise DelegationError, "\#{method} delegated to #{target}, but #{target} is nil"
              end
            else
              raise
            end
          end
        end
      end
      ruby2_keywords(:method_missing)
    RUBY
  end

При создании декораторов часто может появиться такая картина:

class Partition
  def initialize(event)
    @event = event
  end

  def person
    detail.person || creator
  end

  private
    def respond_to_missing?(name, include_private = false)
      @event.respond_to?(name, include_private)
    end

    def method_missing(method, *args, &block)
      @event.send(method, *args, &block)
    end
end

С помощью Module#delegate_missing_to, вышеприведённое сокращается до:

class Partition
  delegate_missing_to :@event

  def initialize(event)
    @event = event
  end

  def person
    detail.person || creator
  end
end

Целевой объект может быть любым вызываемым элементом в объекте, например, переменными экземпляра, методами, константами и т.д.

Делегированный метод должен быть общедоступным в целевом объекте, в противном случае он вызовет DelegationError. Если вы хотите вместо этого вернуть nil, используйте параметр :allow_nil.

Методы marshal_dump и _dump исключены из делегирования из-за возможного вмешательства при вызове Marshal.dump(object), если метод делегирования целевого объекта object добавляет или удаляет переменные экземпляра.

deprecate(*method_names) Показать исходный код
# File activesupport/lib/active_support/core_ext/module/deprecation.rb, line 22
def deprecate(*method_names)
  ActiveSupport::Deprecation.deprecate_methods(self, *method_names)
end
deprecate :foo
deprecate bar: 'message'
deprecate :foo, :bar, baz: 'warning!', qux: 'gone!'

Также можно использовать экземпляр пользовательского деприкаторора:

deprecate :foo, deprecator: MyLib::Deprecator.new
deprecate :foo, bar: "warning!", deprecator: MyLib::Deprecator.new

Пользовательские деприкатороры должны отвечать на метод deprecation_warning(deprecated_method_name, message, caller_backtrace), где можно реализовать ваше поведение предупреждения.

class MyLib::Deprecator
  def deprecation_warning(deprecated_method_name, message, caller_backtrace = nil)
    message = "#{deprecated_method_name} is deprecated and will be removed from MyLibrary | #{message}"
    Kernel.warn message
  end
end
mattr_accessor(*syms, instance_reader: true, instance_writer: true, instance_accessor: true, default: nil, &blk) Показать исходный код
# File activesupport/lib/active_support/core_ext/module/attribute_accessors.rb, line 202
def mattr_accessor(*syms, instance_reader: true, instance_writer: true, instance_accessor: true, default: nil, &blk)
  location = caller_locations(1, 1).first
  mattr_reader(*syms, instance_reader: instance_reader, instance_accessor: instance_accessor, default: default, location: location, &blk)
  mattr_writer(*syms, instance_writer: instance_writer, instance_accessor: instance_accessor, default: default, location: location)
end

Определяет методы доступа как к классу, так и к экземплярам атрибутов класса. Все созданные классовые и экземплярные методы будут public, даже если этот метод вызван с модификатором доступа private или protected.

module HairColors
  mattr_accessor :hair_colors
end

class Person
  include HairColors
end

HairColors.hair_colors = [:brown, :black, :blonde, :red]
HairColors.hair_colors # => [:brown, :black, :blonde, :red]
Person.new.hair_colors # => [:brown, :black, :blonde, :red]

Если подкласс изменяет значение, то это также изменит значение для родительского класса. Аналогично, если родительский класс изменяет значение, то это также изменит значение для подклассов.

class Citizen < Person
end

Citizen.new.hair_colors << :blue
Person.new.hair_colors # => [:brown, :black, :blonde, :red, :blue]

Чтобы опустить метод записи экземпляра, передайте instance_writer: false. Чтобы опустить метод чтения экземпляра, передайте instance_reader: false.

module HairColors
  mattr_accessor :hair_colors, instance_writer: false, instance_reader: false
end

class Person
  include HairColors
end

Person.new.hair_colors = [:brown]  # => NoMethodError
Person.new.hair_colors             # => NoMethodError

Или передайте instance_accessor: false, чтобы опустить оба экземпляра методов.

module HairColors
  mattr_accessor :hair_colors, instance_accessor: false
end

class Person
  include HairColors
end

Person.new.hair_colors = [:brown]  # => NoMethodError
Person.new.hair_colors             # => NoMethodError

Вы можете задать значение по умолчанию для атрибута.

module HairColors
  mattr_accessor :hair_colors, default: [:brown, :black, :blonde, :red]
end

class Person
  include HairColors
end

Person.class_variable_get("@@hair_colors") # => [:brown, :black, :blonde, :red]
Также псевдоним для: cattr_accessor
mattr_reader(*syms, instance_reader: true, instance_accessor: true, default: nil, location: nil) { |: default| ... } Показать исходный код
# File activesupport/lib/active_support/core_ext/module/attribute_accessors.rb, line 53
def mattr_reader(*syms, instance_reader: true, instance_accessor: true, default: nil, location: nil)
  raise TypeError, "module attributes should be defined directly on class, not singleton" if singleton_class?
  location ||= caller_locations(1, 1).first

  definition = []
  syms.each do |sym|
    raise NameError.new("invalid attribute name: #{sym}") unless /\A[_A-Za-z]\w*\z/.match?(sym)

    definition << "def self.#{sym}; @@#{sym}; end"

    if instance_reader && instance_accessor
      definition << "def #{sym}; @@#{sym}; end"
    end

    sym_default_value = (block_given? && default.nil?) ? yield : default
    class_variable_set("@@#{sym}", sym_default_value) unless sym_default_value.nil? && class_variable_defined?("@@#{sym}")
  end

  module_eval(definition.join(";"), location.path, location.lineno)
end

Определяет атрибут класса и создаёт методы чтения для класса и экземпляра. Базовая переменная класса установлена в nil, если она не определена ранее. Все созданные классовые и экземплярные методы будут public, даже если этот метод вызван с модификатором доступа private или protected.

module HairColors
  mattr_reader :hair_colors
end

HairColors.hair_colors # => nil
HairColors.class_variable_set("@@hair_colors", [:brown, :black])
HairColors.hair_colors # => [:brown, :black]

Имя атрибута должно быть допустимым именем метода в Ruby.

module Foo
  mattr_reader :"1_Badname"
end
# => NameError: invalid attribute name: 1_Badname

Чтобы опустить метод чтения экземпляра, передайте instance_reader: false или instance_accessor: false.

module HairColors
  mattr_reader :hair_colors, instance_reader: false
end

class Person
  include HairColors
end

Person.new.hair_colors # => NoMethodError

Вы можете задать значение по умолчанию для атрибута.

module HairColors
  mattr_reader :hair_colors, default: [:brown, :black, :blonde, :red]
end

class Person
  include HairColors
end

Person.new.hair_colors # => [:brown, :black, :blonde, :red]
Также псевдоним для: cattr_reader
END_OF_DOCUMENT_MARKER
mattr_writer(*syms, instance_writer: true, instance_accessor: true, default: nil, location: nil) { |: default| ... } Показать исходный код
# File activesupport/lib/active_support/core_ext/module/attribute_accessors.rb, line 117
def mattr_writer(*syms, instance_writer: true, instance_accessor: true, default: nil, location: nil)
  raise TypeError, "module attributes should be defined directly on class, not singleton" if singleton_class?
  location ||= caller_locations(1, 1).first

  definition = []
  syms.each do |sym|
    raise NameError.new("invalid attribute name: #{sym}") unless /\A[_A-Za-z]\w*\z/.match?(sym)
    definition << "def self.#{sym}=(val); @@#{sym} = val; end"

    if instance_writer && instance_accessor
      definition << "def #{sym}=(val); @@#{sym} = val; end"
    end

    sym_default_value = (block_given? && default.nil?) ? yield : default
    class_variable_set("@@#{sym}", sym_default_value) unless sym_default_value.nil? && class_variable_defined?("@@#{sym}")
  end

  module_eval(definition.join(";"), location.path, location.lineno)
end

Определяет атрибут класса и создаёт методы записи для класса и экземпляра, чтобы разрешить присвоение атрибуту. Все созданные методы класса и экземпляра будут публичными, даже если этот метод вызывается с модификатором доступа private или protected.

module HairColors
  mattr_writer :hair_colors
end

class Person
  include HairColors
end

HairColors.hair_colors = [:brown, :black]
Person.class_variable_get("@@hair_colors") # => [:brown, :black]
Person.new.hair_colors = [:blonde, :red]
HairColors.class_variable_get("@@hair_colors") # => [:blonde, :red]

Чтобы исключить метод записи экземпляра, передайте instance_writer: false или instance_accessor: false.

module HairColors
  mattr_writer :hair_colors, instance_writer: false
end

class Person
  include HairColors
end

Person.new.hair_colors = [:blonde, :red] # => NoMethodError

Вы можете установить значение по умолчанию для атрибута.

module HairColors
  mattr_writer :hair_colors, default: [:brown, :black, :blonde, :red]
end

class Person
  include HairColors
end

Person.class_variable_get("@@hair_colors") # => [:brown, :black, :blonde, :red]
Также алиасирован как: cattr_writer
module_parent() Показать исходный код
# File activesupport/lib/active_support/core_ext/module/introspection.rb, line 35
def module_parent
  module_parent_name ? ActiveSupport::Inflector.constantize(module_parent_name) : Object
end

Возвращает модуль, содержащий этот модуль согласно его имени.

module M
  module N
  end
end
X = M::N

M::N.module_parent # => M
X.module_parent    # => M

Родительским модулем для модулей верхнего уровня и анонимных модулей является Object.

M.module_parent          # => Object
Module.new.module_parent # => Object
module_parent_name() Показать исходный код
# File activesupport/lib/active_support/core_ext/module/introspection.rb, line 10
def module_parent_name
  if defined?(@parent_name)
    @parent_name
  else
    parent_name = name =~ /::[^:]+\z/ ? -$` : nil
    @parent_name = parent_name unless frozen?
    parent_name
  end
end

Возвращает имя модуля, содержащего этот модуль.

M::N.module_parent_name # => "M"
module_parents() Показать исходный код
# File activesupport/lib/active_support/core_ext/module/introspection.rb, line 51
def module_parents
  parents = []
  if module_parent_name
    parts = module_parent_name.split("::")
    until parts.empty?
      parents << ActiveSupport::Inflector.constantize(parts * "::")
      parts.pop
    end
  end
  parents << Object unless parents.include? Object
  parents
end

Возвращает всех родителей этого модуля согласно его имени, от вложенных к внешним. Сам получатель не содержится в результате.

module M
  module N
  end
end
X = M::N

M.module_parents    # => [Object]
M::N.module_parents # => [M, Object]
X.module_parents    # => [M, Object]
redefine_method(method, &block) Показать исходный код
# File activesupport/lib/active_support/core_ext/module/redefine_method.rb, line 17
def redefine_method(method, &block)
  visibility = method_visibility(method)
  silence_redefinition_of_method(method)
  define_method(method, &block)
  send(visibility, method)
end

Заменяет существующее определение метода, если оно есть, на переданный блок в качестве его тела.

redefine_singleton_method(method, &block) Показать исходный код
# File activesupport/lib/active_support/core_ext/module/redefine_method.rb, line 26
def redefine_singleton_method(method, &block)
  singleton_class.redefine_method(method, &block)
end

Заменяет существующее определение метода-сингулярника, если оно есть, на переданный блок в качестве его тела.

remove_possible_method(method) Показать исходный код
# File activesupport/lib/active_support/core_ext/module/remove_method.rb, line 7
def remove_possible_method(method)
  if method_defined?(method) || private_method_defined?(method)
    undef_method(method)
  end
end

Удаляет указанный метод, если он существует.

remove_possible_singleton_method(method) Показать исходный код
# File activesupport/lib/active_support/core_ext/module/remove_method.rb, line 14
def remove_possible_singleton_method(method)
  singleton_class.remove_possible_method(method)
end

Удаляет указанный метод-сингулярник, если он существует.

silence_redefinition_of_method(method) Показать исходный код
# File activesupport/lib/active_support/core_ext/module/redefine_method.rb, line 7
def silence_redefinition_of_method(method)
  if method_defined?(method) || private_method_defined?(method)
    # This suppresses the "method redefined" warning; the self-alias
    # looks odd, but means we don't need to generate a unique name
    alias_method method, method
  end
end

Помечает указанный метод как предназначенный для повторного определения, если он существует. Подавляет предупреждение Ruby о повторном определении метода. Предпочитайте redefine_method, где это возможно.

thread_cattr_accessor(*syms, instance_reader: true, instance_writer: true, instance_accessor: true, default: nil)
Псевдоним для: thread_mattr_accessor
thread_mattr_accessor(*syms, instance_reader: true, instance_writer: true, instance_accessor: true, default: nil) Показать исходный код
# File activesupport/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb, line 152
def thread_mattr_accessor(*syms, instance_reader: true, instance_writer: true, instance_accessor: true, default: nil)
  thread_mattr_reader(*syms, instance_reader: instance_reader, instance_accessor: instance_accessor, default: default)
  thread_mattr_writer(*syms, instance_writer: instance_writer, instance_accessor: instance_accessor)
end

Определяет как методы доступа к атрибутам класса, так и методы доступа к атрибутам экземпляра.

class Account
  thread_mattr_accessor :user
end

Account.user = "DHH"
Account.user     # => "DHH"
Account.new.user # => "DHH"

В отличие от `mattr_accessor`, значения не разделяются с подклассами или родительскими классами. Если подкласс изменяет значение, значение родительского класса не изменяется. Если родительский класс изменяет значение, значение подклассов не изменяется.

class Customer < Account
end

Account.user   # => "DHH"
Customer.user  # => nil
Customer.user  = "Rafael"
Customer.user  # => "Rafael"
Account.user   # => "DHH"

Чтобы исключить метод записи экземпляра, передайте instance_writer: false. Чтобы исключить метод чтения экземпляра, передайте instance_reader: false.

class Current
  thread_mattr_accessor :user, instance_writer: false, instance_reader: false
end

Current.new.user = "DHH"  # => NoMethodError
Current.new.user          # => NoMethodError

Или передайте instance_accessor: false, чтобы исключить оба метода экземпляра.

class Current
  thread_mattr_accessor :user, instance_accessor: false
end

Current.new.user = "DHH"  # => NoMethodError
Current.new.user          # => NoMethodError
Также алиасирован как: thread_cattr_accessor

© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API