Domanda

Non sono riuscito a trovarlo nella documentazione di Rails ma sembra che 'mattr_accessor' sia il Modulo corollario per 'attr_accessor' ( getter & amp; setter) in una normale classe .

Eg. in una classe

class User
  attr_accessor :name

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

Eg. in un modulo

module Authentication
  mattr_accessor :current_user

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

Questo metodo di supporto è fornito da ActiveSupport .

È stato utile?

Soluzione

Rails estende Ruby sia con mattr_accessor (modulo accessor) che cattr_accessor (così come _ reader / _writer versioni). Dato che attr_accessor di Ruby genera metodi getter / setter per istanze , cattr / mattr_accessor fornisce metodi getter / setter nella classe o modulo . Così:

module Config
  mattr_accessor :hostname
  mattr_accessor :admin_email
end

è l'abbreviazione di:

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

Entrambe le versioni consentono di accedere alle variabili a livello di modulo in questo modo:

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

Altri suggerimenti

Ecco la fonte per cattr_accessor

E

Ecco la fonte per mattr_accessor

Come puoi vedere, sono praticamente identici.

Perché ci sono due versioni diverse? A volte vuoi scrivere cattr_accessor in un modulo, quindi puoi usarlo per informazioni sulla configurazione come menziona Avdi .
Tuttavia, cattr_accessor non funziona in un modulo, quindi hanno più o meno copiato il codice per funzionare anche per i moduli.

Inoltre, a volte potresti voler scrivere un metodo di classe in un modulo, in modo tale che ogni qualvolta una classe includa il modulo, ottenga quel metodo di classe così come tutti i metodi di istanza. Anche mattr_accessor ti consente di farlo.

Tuttavia, nel secondo scenario, il suo comportamento è piuttosto strano. Osservare il codice seguente, in particolare i bit @@ 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"
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top