Rails模块中的mattr_accessor是什么?


107

我在Rails文档中找不到真正的东西,但似乎'mattr_accessor'是普通Ruby 类中'attr_accessor'(getter&setter)的模块推论。

例如。在课堂上

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

Answers:


181

Rails通过mattr_accessor(模块访问器)和cattr_accessor(以及_ reader/ _writer版本)扩展了Ruby 。作为Ruby的attr_accessor生成用于getter / setter方法的实例cattr/mattr_accessor提供在吸气/ 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 = "admin@example.com"
>> Config.hostname # => "example.com"
>> Config.admin_email # => "admin@example.com"

1
在示例中,您解释mattr_accessor了类实例变量(@variables)的缩写,但是源代码似乎表明它们实际上是在设置/读取类变量。您能解释一下这种区别吗?
sandre89 '18

38

这是 cattr_accessor

这是 mattr_accessor

如您所见,它们几乎相同。

至于为什么有两个不同的版本?有时您想编写cattr_accessor模块,因此可以将其用于配置信息,例如Avdi提及
但是,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"

当直接设置default_url_options(mattr_accessor)时,这是一个让我非常痛苦的陷阱。一旦类将以一种方式设置它们,而另一种将以不同的方式设置它们,从而创建无效的链接。
埃里克·戴维斯

在最新版本的Rails cattr_*中,现在是的别名mattr_*。参见cattr_accessor源代码
ouranos '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.