Rails 模块中的 mattr_accessor 是什么?

发布于 2024-07-06 18:08:59 字数 556 浏览 6 评论 0原文

我在 Rails 文档中找不到这个,但似乎 'mattr_accessor''attr_accessor'Module 必然结果(getter & setter)在普通的 Ruby 中。

例如。 在课堂上

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

I couldn't really find this in Rails documentation but it seems like 'mattr_accessor' is the Module corollary for 'attr_accessor' (getter & setter) in a normal Ruby class.

Eg. in a class

class User
  attr_accessor :name

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

Eg. in a module

module Authentication
  mattr_accessor :current_user

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

This helper method is provided by ActiveSupport.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

叹倦 2024-07-13 18:08:59

Rails 使用 mattr_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

两个版本都允许您访问模块级变量,如下所示:

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

Rails extends Ruby with both mattr_accessor (Module accessor) and cattr_accessor (as well as _reader/_writer versions). As Ruby's attr_accessor generates getter/setter methods for instances, cattr/mattr_accessor provide getter/setter methods at the class or module level. Thus:

module Config
  mattr_accessor :hostname
  mattr_accessor :admin_email
end

is short for:

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

Both versions allow you to access the module-level variables like so:

>> Config.hostname = "example.com"
>> Config.admin_email = "[email protected]"
>> Config.hostname # => "example.com"
>> Config.admin_email # => "[email protected]"
如果没有 2024-07-13 18:08:59

这里是 <代码>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"

Here's the source for cattr_accessor

And

Here's the source for mattr_accessor

As you can see, they're pretty much identical.

As to why there are two different versions? Sometimes you want to write cattr_accessor in a module, so you can use it for configuration info like Avdi mentions.
However, cattr_accessor doesn't work in a module, so they more or less copied the code over to work for modules also.

Additionally, sometimes you might want to write a class method in a module, such that whenever any class includes the module, it gets that class method as well as all the instance methods. mattr_accessor also lets you do this.

However, in the second scenario, it's behaviour is pretty strange. Observe the following code, particularly note the @@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"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文