Question

Je ne pouvais pas vraiment trouver cela dans la documentation Rails, mais il semble que 'mattr_accessor' soit le corollaire du module pour 'attr_accessor' ( getter & setter) dans une classe Ruby normale .

Par exemple. dans une classe

class User
  attr_accessor :name

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

Par exemple. dans un module

module Authentication
  mattr_accessor :current_user

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

Cette méthode d'assistance est fournie par ActiveSupport .

Était-ce utile?

La solution

Rails étend Ruby avec mattr_accessor (accesseur de module) et cattr_accessor (ainsi que _ lecteur / _writer versions). Comme attr_accessor de Ruby génère des méthodes getter / setter pour les instances , cattr / mattr_accessor fournit des méthodes getter / setter à la classe . ou niveau module . Ainsi:

module Config
  mattr_accessor :hostname
  mattr_accessor :admin_email
end

est l'abréviation 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

Les deux versions vous permettent d'accéder aux variables de niveau module comme suit:

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

Autres conseils

ici la source de cattr_accessor

Et

ici la source de mattr_accessor

Comme vous pouvez le constater, ils sont pratiquement identiques.

Pourquoi existe-t-il deux versions différentes? Parfois, vous voulez écrire cattr_accessor dans un module afin de pouvoir l'utiliser pour les informations de configuration comme mentionné par Avdi .
Cependant, cattr_accessor ne fonctionne pas dans un module, ils ont donc plus ou moins copié le code pour qu'il fonctionne également avec les modules.

De plus, vous pouvez parfois vouloir écrire une méthode de classe dans un module, de telle sorte que chaque fois qu'une classe inclut le module, elle obtient cette méthode ainsi que toutes les méthodes d'instance. mattr_accessor vous permet également de le faire.

Cependant, dans le deuxième scénario, son comportement est assez étrange. Observez le code suivant, notez en particulier les 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"
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top