Rails 模块中的 mattr_accessor 是啥?
Posted
技术标签:
【中文标题】Rails 模块中的 mattr_accessor 是啥?【英文标题】:What is mattr_accessor in a Rails module?Rails 模块中的 mattr_accessor 是什么? 【发布时间】:2010-09-16 04:20:30 【问题描述】:我在 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 提供。
【问题讨论】:
【参考方案1】:Rails 使用mattr_accessor
(模块访问器)和cattr_accessor
(以及_reader
/_writer
版本)扩展了Ruby。由于 Ruby 的 attr_accessor
为 instances 生成 getter/setter 方法,cattr/mattr_accessor
在 class 或 module 级别提供 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 = "admin@example.com"
>> Config.hostname # => "example.com"
>> Config.admin_email # => "admin@example.com"
【讨论】:
在您的示例中,您解释说mattr_accessor
是类实例变量的缩写(@variable
s),但源代码似乎显示它们实际上是在设置/读取类变量。你能解释一下这个区别吗?【参考方案2】:
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"
【讨论】:
当直接设置 default_url_options(一个 mattr_accessor)时,这是一个让我很难受的问题。一旦类将它们设置为一种方式,另一种方式将它们设置为不同的方式,从而创建无效链接。 在最新版本的 Rails 中,cattr_*
现在是 mattr_*
的别名。见cattr_accessor
source以上是关于Rails 模块中的 mattr_accessor 是啥?的主要内容,如果未能解决你的问题,请参考以下文章
了解 Ruby on Rails 6 中的路由 + 模块/类名称 [以及在此上下文中模块是啥]
如何在 Rails 中正确使用控制器辅助模块,以及如何连接这些辅助模块?