2008-10-09 17 views
91

ja naprawdę nie mogłem znaleźć to w dokumentacji Rails, ale wydaje się „mattr_accessor” jest Moduł następstwo dla „attr_accessor” (getter & setter) w normalnym Ruby klasy.Co to jest mattr_accessor w module Rails?

Np. w klasie

class User 
    attr_accessor :name 

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

Np. w module

module Authentication 
    mattr_accessor :current_user 

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

Ta metoda pomocnik jest przez ActiveSupport.

Odpowiedz

159

szyn rozciąga Ruby zarówno mattr_accessor (moduł accessor) i cattr_accessor (jak również _ reader/_writer wersje). Jako Ruby attr_accessor generuje getter/pobierz na przypadkach, cattr/mattr_accessor zapewniają sposoby pobierająca/pobierz na tym klasy lub modułu poziomu. Zatem:

module Config 
    mattr_accessor :hostname 
    mattr_accessor :admin_email 
end 

jest skrótem od:

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 

Obie wersje pozwalają na dostęp do zmiennych moduł poziomie tak:

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

w twoich przykładach wytłumaczyć, że 'mattr_accessor' byłby krótki dla zmiennych instancji klasy (' @ variable's), ale kod źródłowy wydaje się ujawniać, że są faktycznie ustawia/czyta zmienne klasy. Czy mógłbyś wyjaśnić tę różnicę? – sandre89

35

Here's the source for cattr_accessor

And

Here's the source for mattr_accessor

Jak widać, są prawie identyczne.

Dlaczego są dwie różne wersje? Czasami chcesz napisać cattr_accessor w module, więc możesz go użyć do informacji o konfiguracji like Avdi mentions.
Jednak cattr_accessor nie działa w module, więc mniej lub bardziej skopiował kod do pracy dla modułów również.

Dodatkowo, czasami możesz chcieć napisać metodę klasy w module tak, że ilekroć jakakolwiek klasa zawiera moduł, pobiera tę metodę klasy, jak również wszystkie metody instancji. mattr_accessor również pozwala to zrobić.

Jednak w drugim scenariuszu zachowanie jest dość dziwne. Przestrzegać poniższy kod, szczególnie zwróć uwagę na @@mattr_in_module bity

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

To było trochę trudne, gdy ustawiam default_url_options bezpośrednio (mattr_accessor). Gdy klasa ustawi je w taki czy inny sposób, ustawi je w inny sposób, tworząc w ten sposób nieprawidłowe linki. –

+0

W najnowszej wersji Railsów 'cattr_ *' są teraz aliasami dla 'mattr_ *'. Zobacz źródło '' cattr_accessor' (https://github.com/rails/rails/blob/4-2-stable/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb) – ouranos