2008-10-09 34 views
91

我真的無法找到這Rails文檔,但它似乎像「mattr_accessor」模塊推論在一般的Ruby 「attr_accessor」(吸氣& setter方法)。Rails模塊中的mattr_accessor是什麼?

例如,在一類

class User 
    attr_accessor :name 

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

例如,一個模塊

module Authentication 
    mattr_accessor :current_user 

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

在這個輔助方法由的ActiveSupport提供。

回答

159

Rails通過mattr_accessor(模塊訪問器)和cattr_accessor(以及_ reader/_writer版本)擴展了Ruby。作爲Ruby的attr_accessor生成用於實例cattr/mattr_accessor提供在模塊水平getter/setter方法getter/setter方法。因此:

module Config 
    mattr_accessor :hostname 
    mattr_accessor :admin_email 
end 

是短期的:

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 

兩個版本都允許您訪問的模塊級的變量,像這樣:

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

在你的例子,你解釋說,`mattr_accessor`將簡稱類的實例變量(`@ variable`s),但似乎源代碼來揭示他們是實際設置/讀取類變量。你能解釋一下這個區別嗎? – sandre89 2018-01-17 01:19:04

35

Here's the source for cattr_accessor

而且

Here's the source for mattr_accessor

正如你所看到的,它們幾乎完全相同。

至於爲什麼有兩個不同的版本?有時候你想在模塊中寫cattr_accessor,所以你可以用它來配置信息like Avdi mentions
但是,cattr_accessor不能在模塊中工作,所以它們或多或少地將代碼複製到模塊中。

此外,有時您可能想要在模塊中編寫類方法,以便每當任何類包含該模塊時,都會獲取該類方法以及所有實例方法。 mattr_accessor也可以讓你這樣做。

但是,在第二種情況下,它的行爲非常奇怪。注意下面的代碼,特別注意@@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" 
+0

當直接設置default_url_options(mattr_accessor)時,這是一個難以置信的難題。一旦課程將他們設置爲一種方式,另一種方式將他們設置爲不同的方式,從而創建無效的鏈接。 – 2009-02-25 07:20:48