Spec-Zone.ru › Ruby on Rails 7.1

class Module

Parent:
Объект
Included modules:
Module::Concerning

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

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

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

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

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

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

Константы

DELEGATION_RESERVED_KEYWORDS
DELEGATION_RESERVED_METHOD_NAMES
RUBY_ЗАРЕЗЕРВИРОВАННЫЕ_КЛЮЧЕВЫЕ_СЛОВА

Атрибуты

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
deep_dup() Показать исходный код
# File activesupport/lib/active_support/core_ext/object/deep_dup.rb, line 64
def deep_dup
  if name.nil?
    super
  else
    self
  end
end

Возвращает копию модуля или класса, если он анонимный. Если он именован, возвращает self.

Object.deep_dup == Object # => true
klass = Class.new
klass.deep_dup == klass # => false
Вызывает метод суперкласса Object#deep_dup
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

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

  method_def = []
  method_names = []

  method_def << "self.private" if private

  methods.each 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 /[^\]]=\z/.match?(method)
        "arg"
      else
        method_object =
          begin
            if to.is_a?(Module)
              to.method(method)
            elsif receiver == "self.class"
              method(method)
            end
          rescue NameError
            # Do nothing. Fall back to `"..."`
          end

        if method_object
          parameters = method_object.parameters

          if (parameters.map(&:first) & [:opt, :rest, :keyreq, :key, :keyrest]).any?
            "..."
          else
            defn = parameters.filter_map { |type, arg| arg if type == :req }
            defn << "&block"
            defn.join(", ")
          end
        else
          "..."
        end
      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})" <<
        "  _ = #{receiver}" <<
        "  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})" <<
        "  _ = #{receiver}" <<
        "  _.#{method}(#{definition})" <<
        "rescue NoMethodError => e" <<
        "  if _.nil? && e.name == :#{method}" <<
        %(   raise DelegationError, "#{self}##{method_name} delegated to #{receiver}.#{method}, but #{receiver} is nil: \#{self.inspect}") <<
        "  else" <<
        "    raise" <<
        "  end" <<
        "end"
    end
  end
  module_eval(method_def.join(";"), file, line)
  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'

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

delegate_missing_to(target, allow_nil: nil) Показать исходный код
# File activesupport/lib/active_support/core_ext/module/delegation.rb, line 318
  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, deprecator: nil, **options) Показать исходный код
# File activesupport/lib/active_support/core_ext/module/deprecation.rb, line 17
def deprecate(*method_names, deprecator: nil, **options)
  if deprecator.is_a?(ActiveSupport::Deprecation)
    deprecator.deprecate_methods(self, *method_names, **options)
  elsif deprecator
    # we just need any instance to call deprecate_methods, but the deprecation will be emitted by deprecator
    ActiveSupport.deprecator.deprecate_methods(self, *method_names, **options, deprecator: deprecator)
  else
    ActiveSupport.deprecator.warn("Module.deprecate without a deprecator is deprecated")
    ActiveSupport::Deprecation._instance.deprecate_methods(self, *method_names, **options)
  end
end
deprecate :foo, deprecator: MyLib.deprecator
deprecate :foo, bar: "warning!", deprecator: MyLib.deprecator

Депрекатор, как правило, является экземпляром ActiveSupport::Deprecation, но вы также можете передать любой объект, который отвечает на 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 208
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]
  mattr_accessor(:hair_styles) { [:long, :short] }
end

class Person
  include HairColors
end

Person.class_variable_get("@@hair_colors") # => [:brown, :black, :blonde, :red]
Person.class_variable_get("@@hair_styles") # => [:long, :short]
Также псевдоним для: 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 55
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]
  mattr_reader(:hair_styles) { [:long, :short] }
end

class Person
  include HairColors
end

Person.new.hair_colors # => [:brown, :black, :blonde, :red]
Person.new.hair_styles # => [:long, :short]
Также алиас: 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 121
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]
  mattr_writer(:hair_styles) { [:long, :short] }
end

class Person
  include HairColors
end

Person.class_variable_get("@@hair_colors") # => [:brown, :black, :blonde, :red]
Person.class_variable_get("@@hair_styles") # => [:long, :short]
Также алиас: cattr_writer
module_parent() Показать исходный код
# File activesupport/lib/active_support/core_ext/module/introspection.rb, line 34
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 9
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 50
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 170
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

Значение по умолчанию может быть указано с помощью опции :default. Поскольку к значению по умолчанию могут иметь доступ несколько потоков, значения по умолчанию, не являющиеся замороженными, будут dup и заморожены.

Также алиас: thread_cattr_accessor

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

Spec-Zone.ru

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