2008-10-09 7 views
91

ich das nicht wirklich in Rails Dokumentation finden könnte, aber es scheint, wie 'mattr_accessor' ist die Modul logische Folge für 'attr_accessor' (Getter & Setter) in einer normalen Ruby-Klasse.Was ist mattr_accessor in einem Rails-Modul?

Eg. in einer Klasse

class User 
    attr_accessor :name 

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

z. in einem Modul

module Authentication 
    mattr_accessor :current_user 

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

Diese Hilfsmethode wird von Active vorgesehen.

Antwort

159

Rails erstreckt Rubin sowohl mit mattr_accessor (Modul Accessor) und cattr_accessor (sowie _ reader/_writer Versionen). Als Ruby attr_accessor erzeugt Get-/Set-Methoden für Instanzen, cattr/mattr_accessor Get-/Set-Methoden an der Klasse oder Modul Ebene. Also:

module Config 
    mattr_accessor :hostname 
    mattr_accessor :admin_email 
end 

ist die Abkürzung für:

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 

Beide Versionen können Sie die Variablen auf Modulebene zugreifen wie so:

>> Config.hostname = "example.com" 
>> Config.admin_email = "[email protected]" 
>> Config.hostname # => "example.com" 
>> Config.admin_email # => "[email protected]" 
+0

In Ihren Beispielen erklären Sie, dass 'mattr_accessor' für Klasse Instanzvariablen kurz sein würde (' @ variable's), aber der Quellcode scheint zu zeigen, sie sind Klassenvariablen setzen/lesen. Könnten Sie bitte diesen Unterschied erklären? – sandre89

35

Here's the source for cattr_accessor

Und

Here's the source for mattr_accessor

Wie Sie sehen können, sind sie ziemlich identisch.

Warum gibt es zwei verschiedene Versionen? Manchmal möchten Sie cattr_accessor in ein Modul schreiben, damit Sie es für Konfigurationsinformationen like Avdi mentions verwenden können.
Allerdings funktioniert cattr_accessor nicht in einem Modul, so dass sie mehr oder weniger den Code kopiert, um auch für Module zu arbeiten.

Manchmal möchten Sie vielleicht auch eine Klassenmethode in einem Modul schreiben, sodass jedes Mal, wenn eine Klasse das Modul enthält, diese Klassenmethode sowie alle Instanzmethoden abgerufen werden. mattr_accessor können Sie dies auch tun.

Im zweiten Szenario ist das Verhalten jedoch ziemlich seltsam. Beachten Sie den folgenden Code, besonders beachten Sie die @@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" 
+0

Das war ein Fehler, der mich ziemlich hart hat, wenn ich default_url_options direkt setze (ein mattr_accessor). Sobald die Klasse sie in eine Richtung und die andere in eine andere Richtung bringen würde, würden sie einen anderen Weg einschlagen und somit ungültige Verknüpfungen erzeugen. –

+0

In der neuesten Version von Rails 'cattr_ *' sind jetzt Aliase für 'mattr_ *'. Siehe die Quelle "cattr_accessor" (https://github.com/rails/rails/blob/4-2-stable/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb). – ouranos

Verwandte Themen