rails concerns ruby-on-rails ruby class module activesupport

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"