2008-10-09 10 views
91

realmente no pude encontrar esto en la documentación de los carriles, pero parece que 'mattr_accessor' es el Módulo corolario de 'attr_accessor' (captador & colocador) en una clase normal de Rubí .¿Qué es mattr_accessor en un módulo de Rails?

Por ejemplo. en una clase

class User 
    attr_accessor :name 

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

Eg. 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 es proporcionada por ActiveSupport.

Respuesta

159

Rails extiende rubí con tanto mattr_accessor (de acceso módulo) y cattr_accessor (así como _ reader/_writer versiones). Como attr_accessor de Ruby genera métodos de captador/definidor para casos, cattr/mattr_accessor proporcionar métodos de captador/definidor en el clase o módulo nivel. Por lo tanto:

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 este modo:

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

En sus ejemplos, se explica que 'mattr_accessor' sería la abreviatura de las variables de instancia de clase (' @ variable's), pero el código fuente parece revelar que son en realidad está configurando/leyendo variables de clase. ¿Podría explicar esta diferencia? – sandre89

35

Here's the source for cattr_accessor

Y

Here's the source for mattr_accessor

Como puede ver, son prácticamente idénticos.

¿Por qué hay dos versiones diferentes? Algunas veces desea escribir cattr_accessor en un módulo, de modo que puede usarlo para la información de configuración like Avdi mentions.
Sin embargo, cattr_accessor no funciona en un módulo, por lo 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 le permite hacer esto.

Sin embargo, en el segundo escenario, su comportamiento es bastante extraño. Observe el siguiente código, sobre todo en cuenta los bits de @@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" 
+0

Esto fue una sorpresa que me mordió bastante duro al establecer default_url_options directamente (un mattr_accessor). Una vez que la clase los establece de una manera y otra los establece de una manera diferente, creando así enlaces no válidos. –

+0

En la última versión de Rails 'cattr_ *' ahora son alias para 'mattr_ *'. Ver la fuente ['cattr_accessor'] (https://github.com/rails/rails/blob/4-2-stable/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb) – ouranos

Cuestiones relacionadas