Что такое mattr_accessor в модуле Rails? - программирование
Подтвердить что ты не робот

Что такое mattr_accessor в модуле Rails?

Я не мог найти это в документации Rails, но похоже, что "mattr_accessor" - это Модуль для 'attr_accessor' ( getter и setter) в обычном Ruby классе.

Eg. в классе

class User
  attr_accessor :name

  def set_fullname
    @name = "#{self.first_name} #{self.last_name}"
  end
end

Eg. в модуле

module Authentication
  mattr_accessor :current_user

  def login
    @current_user = session[:user_id] || nil
  end
end

Этот вспомогательный метод предоставляется ActiveSupport.

4b9b3361

Ответ 1

Rails расширяет Ruby с помощью mattr_accessor (Accessor Access) и cattr_accessor (а также версий reader/_writer). Поскольку Ruby attr_accessor генерирует методы getter/setter для экземпляров, cattr/mattr_accessor предоставляет методы getter/setter на уровне класса или модуля. Таким образом:

module Config
  mattr_accessor :hostname
  mattr_accessor :admin_email
end

сокращается для:

module Config
  def self.hostname
    @hostname
  end
  def self.hostname=(hostname)
    @hostname = hostname
  end
  def self.admin_email
    @admin_email
  end
  def self.admin_email=(admin_email)
    @admin_email = admin_email
  end
end

Обе версии позволяют вам обращаться к переменным уровня модуля следующим образом:

>> Config.hostname = "example.com"
>> Config.admin_email = "[email protected]"
>> Config.hostname # => "example.com"
>> Config.admin_email # => "[email protected]"

Ответ 2

Здесь источник для cattr_accessor

И

Здесь источник для mattr_accessor

Как вы можете видеть, они почти идентичны.

Почему существуют две разные версии? Иногда вы хотите написать cattr_accessor в модуле, чтобы вы могли использовать его для информации о конфигурации как упоминания Avdi.
Однако cattr_accessor не работает в модуле, поэтому они более или менее скопировали код для работы с модулями.

Кроме того, иногда вам может понадобиться написать метод класса в модуле, так что всякий раз, когда какой-либо класс включает модуль, он получает этот метод класса, а также все методы экземпляра. mattr_accessor также позволяет вам делать это.

Однако во втором сценарии это поведение довольно странно. Соблюдайте следующий код, особенно обратите внимание на @@mattr_in_module bits

module MyModule
  mattr_accessor :mattr_in_module
end

class MyClass
  include MyModule
  def self.get_mattr; @@mattr_in_module; end # directly access the class variable
end

MyModule.mattr_in_module = 'foo' # set it on the module
=> "foo"

MyClass.get_mattr # get it out of the class
=> "foo"

class SecondClass
  include MyModule
  def self.get_mattr; @@mattr_in_module; end # again directly access the class variable in a different class
end

SecondClass.get_mattr # get it out of the OTHER class
=> "foo"