Qu'est-ce que mattr accessor dans un module Rails?

Je ne pouvais pas vraiment trouver cela dans la documentation des Rails, mais il semble que 'mattr_accessor' soit le Module corollaire pour 'attr_accessor' (getter & setter) dans un Ruby normal classe .

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'aide est fournie par ActiveSupport .

97
demandé sur JasonOng 2008-10-09 05:15:15

2 réponses

rallonge Ruby avec les versions mattr_accessor (module accessor) et cattr_accessor (ainsi que _ reader / _writer ). Comme Ruby attr_accessor génère des méthodes getter/setter pour instances , cattr/mattr_accessor fournir des méthodes getter/setter au niveau classe ou 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 permet d'accéder aux variables au niveau du module comme ceci:

>> Config.hostname = "example.com"
>> Config.admin_email = "admin@example.com"
>> Config.hostname # => "example.com"
>> Config.admin_email # => "admin@example.com"
165
répondu Avdi 2017-12-07 11:51:08

Voici la source de cattr_accessor

et

Voici la source de mattr_accessor

Comme vous pouvez le voir, ils sont à peu près identiques.

pourquoi il y a deux versions différentes? Parfois, vous voulez écrire cattr_accessor dans un module, de sorte que vous pouvez l'utiliser pour les informations de configuration comme Avdi mentionne .

Cependant, cattr_accessor ne fonctionne pas dans un module, de sorte qu'ils ont plus ou moins copié le code pour travailler pour les modules aussi.

de plus, parfois vous pourriez vouloir écrire une méthode de classe dans un module, de sorte que chaque fois que n'importe quelle classe inclut le module, il obtient cette méthode de classe aussi bien que toutes les méthodes d'instance. mattr_accessor vous permet également de le faire.

cependant, dans le second scénario, son comportement est assez étrange. Observez le code suivant, en particulier notez le @@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"
36
répondu Orion Edwards 2017-05-23 12:18:10