Je ne pouvais pas vraiment trouver cela dans la documentation Rails mais il semble que 'mattr_accessor' est le corollaire Module pour ' attr_accessor ' (getter & setter) dans une normale Ruby class.
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.
Rails étend Ruby avec les deux mattr_accessor
(Accesseur de module) et cattr_accessor
(ainsi que _reader
/_writer
versions). Comme Ruby attr_accessor
génère des méthodes getter/setter pour instances, cattr/mattr_accessor
fournit des méthodes getter/setter au niveau class ou module. Donc:
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 = "[email protected]"
>> Config.hostname # => "example.com"
>> Config.admin_email # => "[email protected]"
Voici la source de cattr_accessor
Et
Voici la source de mattr_accessor
Comme vous pouvez le voir, ils sont à peu près identiques.
Quant à savoir pourquoi il existe deux versions différentes? Parfois, vous voulez écrire cattr_accessor
dans un module, vous pouvez donc l'utiliser pour des informations de configuration comme Avdi le mentionne .
Pourtant, cattr_accessor
ne fonctionne pas dans un module, ils ont donc plus ou moins copié le code pour fonctionner également pour les modules.
De plus, vous pouvez parfois vouloir écrire une méthode de classe dans un module, de sorte que chaque fois qu'une classe inclut le module, elle obtient cette méthode de classe 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 particulièrement le @@mattr_in_module
morceaux
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"