Что такое mattr_accessor в модуле Rails?
-
06-07-2019 - |
Вопрос
Я не смог найти это в документации Rails, но похоже 'mattr_accessor' это Модуль следствие для 'attr_accessor' (геттер и сеттер) в обычном Ruby сорт.
Например.в классе
class User
attr_accessor :name
def set_fullname
@name = "#{self.first_name} #{self.last_name}"
end
end
Например.в модуле
module Authentication
mattr_accessor :current_user
def login
@current_user = session[:user_id] || nil
end
end
Этот вспомогательный метод предоставляется Активная поддержка.
Решение
Rails расширяет Ruby обеими mattr_accessor
(аксессуар к модулю) и cattr_accessor
(а также _reader
/_writer
версии).Как у Руби attr_accessor
генерирует методы получения/установки для случаи, cattr/mattr_accessor
предоставить методы получения/установки в сорт или модуль уровень.Таким образом:
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 = "admin@example.com"
>> Config.hostname # => "example.com"
>> Config.admin_email # => "admin@example.com"
Другие советы
Вот источник для cattr_accessor
И
Вот источник для mattr_accessor
Как видите, они практически идентичны.
А почему существуют две разные версии?Иногда хочется написать cattr_accessor
в модуле, поэтому вы можете использовать его для информации о конфигурации как упоминает Авди.
Однако, cattr_accessor
не работает в модуле, поэтому они более или менее скопировали код, чтобы он работал и для модулей.
Кроме того, иногда вам может потребоваться написать метод класса в модуле, чтобы всякий раз, когда какой-либо класс включает модуль, он получал этот метод класса, а также все методы экземпляра. mattr_accessor
также позволяет вам это сделать.
Однако во втором сценарии его поведение довольно странное.Соблюдайте следующий код, особенно обратите внимание на @@mattr_in_module
биты
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"