ruby on rails - concerns - ¿Qué es mattr_accessor en un módulo de Rails?
rails concerns folder (2)
Realmente no pude encontrar esto en la documentación de Rails, pero parece que ''mattr_accessor'' es el corolario del módulo para ''attr_accessor'' (getter & setter) en una clase normal de Ruby.
P.ej. en una clase
class User
attr_accessor :name
def set_fullname
@name = "#{self.first_name} #{self.last_name}"
end
end
P.ej. en un módulo
module Authentication
mattr_accessor :current_user
def login
@current_user = session[:user_id] || nil
end
end
Este método de ayuda lo proporciona ActiveSupport .
Los rieles se extienden Ruby con el mattr_accessor
( mattr_accessor
módulo) y cattr_accessor
(así como las versiones de _ reader
/ _writer
). Como el attr_accessor
de Ruby genera métodos getter / setter para instancias , cattr/mattr_accessor
proporciona métodos getter / setter a nivel de clase o módulo . Así:
module Config
mattr_accessor :hostname
mattr_accessor :admin_email
end
es la abreviatura de:
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
Ambas versiones le permiten acceder a las variables de nivel de módulo de esta manera:
>> Config.hostname = "example.com"
>> Config.admin_email = "[email protected]"
>> Config.hostname # => "example.com"
>> Config.admin_email # => "[email protected]"
Aquí está la fuente de cattr_accessor
Y
Aquí está la fuente para mattr_accessor
Como puede ver, son bastante idénticos.
¿En cuanto a por qué hay dos versiones diferentes? Algunas veces quiere escribir cattr_accessor
en un módulo, para que pueda usarlo para información de configuración como Avdi mentions .
Sin embargo, cattr_accessor
no funciona en un módulo, así que más o menos copiaron el código para que funcione también para los módulos.
Además, a veces es posible que desee escribir un método de clase en un módulo, de modo que cada vez que una clase incluya el módulo, obtenga ese método de clase, así como todos los métodos de instancia. mattr_accessor
también te permite hacer esto.
Sin embargo, en el segundo escenario, su comportamiento es bastante extraño. Observe el siguiente código, especialmente tenga en cuenta los bits @@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"