Что такое 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.
Ответы
Ответ 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"