什么是Rails模块中的mattr_accessor?

我在Rails文档中找不到这个,但是在正常的Ruby 类中, 'mattr_accessor''attr_accessor' (getter&setter)的模块推论。

例如。 在一个class级

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提供。

Rails使用mattr_accessor (Module accessor)和cattr_accessor (以及_ reader / _writer版本)来扩展Ruby。 由于Ruby的attr_accessor实例生成了getter / setter方法, cattr/mattr_accessor模块级别提供了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 

这两个版本都允许您访问模块级别的variables,如下所示:

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

这是cattr_accessor的源cattr_accessor

这是mattr_accessor的源mattr_accessor

正如你所看到的,它们几乎完全相同。

至于为什么有两个不同的版本? 有时候你想在模块中写cattr_accessor ,所以你可以用它来configuration信息, 比如Avdi提到 。
但是, cattr_accessor在模块中不起作用,所以它们或多或less地将代码复制到模块中。

此外,有时您可能想要在模块中编写一个类方法,例如,只要有任何类包含该模块,就会得到该类方法以及所有实例方法。 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"