Pregunta

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 & amp; setter) en una clase normal de Ruby .

Ej. en una clase

class User
  attr_accessor :name

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

Ej. en un módulo

module Authentication
  mattr_accessor :current_user

  def login
    @current_user = session[:user_id] || nil
  end
end

Este método auxiliar lo proporciona ActiveSupport .

¿Fue útil?

Solución

Rails extiende Ruby con mattr_accessor (Módulo de acceso) y cattr_accessor (así como con _ reader / _writer versiones). Como attr_accessor de Ruby genera métodos getter / setter para instancias , cattr / mattr_accessor proporciona métodos getter / setter en la 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 esta manera:

>> Config.hostname = "example.com"
>> Config.admin_email = "admin@example.com"
>> Config.hostname # => "example.com"
>> Config.admin_email # => "admin@example.com"

Otros consejos

Aquí está la fuente de cattr_accessor

Y

Aquí está la fuente de mattr_accessor

Como puede ver, son bastante idénticos.

¿Por qué hay dos versiones diferentes? A veces desea escribir cattr_accessor en un módulo, por lo que puede usarlo para la información de configuración como Avdi menciona .
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 siempre que cualquier 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, especialmente los @@ 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"
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top