Spec-Zone.ru › Ruby on Rails 6.1

класс Module

Родитель:
Объект
Включенные модули:
Модуль::Concerning

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

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

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

Константы

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 = if /[^\]]=$/.match?(method)
      "arg"
    elsif RUBY_VERSION >= "2.7"
      "..."
    else
      "*args, &block"
    end

    # 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'

Делегированные методы по умолчанию являются публичными. Используйте 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'

Метод целевого объекта должен быть публичным, иначе будет поднято исключение NoMethodError.

delegate_missing_to(target, allow_nil: nil) Показать исходный код
# File activesupport/lib/active_support/core_ext/module/delegation.rb, line 295
  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) if respond_to?(:ruby2_keywords, true)
    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 200
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

Определяет как методы доступа к атрибутам класса, так и методы доступа к атрибутам экземпляра. Все созданные методы класса и экземпляра будут публичными, даже если этот метод вызывается с модификаторами доступа 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 51
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, если она не определена ранее. Все созданные методы класса и экземпляра будут публичными, даже если этот метод вызывается с модификаторами доступа 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
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 115
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 143
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"

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

class Customer < Account
end

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–2020 David Heinemeier Hansson
Licensed under the MIT License.

Spec-Zone.ru

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