有趣的问题!我在 Rails 项目的所有库源中搜索了'hash-with-ivars',只找到了一个地方:psych ruby library 用于(反)序列化任意对象到YAML 和从YAML。具体来说,这些是指向 reading 和 writing 这个 YAML 结构的源代码的链接。
在 Rails 教程的 Chapter 7 中,此输出是 debug(params) 命令的输出,指示您将其放入模板中。 debug 命令显然调用了psych 库来显示对象的可读表示(在本例中为params)。
现在,params - 用于保存从 URL 或表单传递的参数的通用 Rails 数据结构 - 是一个行为类似于 Hash 但不是纯哈希的对象:它是 @987654339 类的实例@ 是Hash 的子类,让我们看看class definition:
module ActionController
# ...
class Parameters < ActiveSupport::HashWithIndifferentAccess
# ...
end
end
而HashWithIndifferentAccess 是Hash 的直接子类。
作为Hash 的子类,params 对象可以保存除散列本身之外的其他数据,这是psych 在尝试以可读形式打印对象时实际支持的。除了打印所有散列元素(在elements 键下),它还尝试列出对象的所有实例变量,并在ivars 键下打印它。
所以,总而言之,这个调试打印只是说被调试的对象是ActionController::Parameters 类的一个实例,它是Hash 的子类,除了它的散列元素还有一个@permitted 实例变量已定义,当前设置为false。顺便说一下,controller 和action 这两个元素是 Rails 内部用于路由的参数。
当你再次查看类的源代码时,你确实会在构造函数中找到@permitted 变量:
class Parameters < ActiveSupport::HashWithIndifferentAccess
# ...
def initialize(attributes = nil)
super(attributes)
@permitted = self.class.permit_all_parameters
end
end
最后,从documentation我们可以得出结论,@permitted变量持有params权限的状态。 IE。在使用permit 方法允许参数后,它被设置为true:
permitted = params.require(:person).permit(:name, :age)
permitted.permitted? # this prints out the @permitted instance variable
# => true
更新:为什么 RailsTutorial 的调试输出不同
RailsTutorial 中的调试输出稍有不同 - 它不会打印 ivars。为什么?这是因为序列化hash-with-ivars 的功能已添加到psych gem 的version 2.0.9 中。 psych gem 现在是 Ruby 标准库的一部分,并且它的这个特定版本在 stdlib 2.3.0 preview1 版本中已成为added。
因此,神秘的不同输出有一个简单的解释:RailsTutorial 作者很可能在编写本书时使用了 ruby 2.2 或更早版本,而这个 ruby 版本尚未在Hash 调试输出中显示实例变量。其实教程中有提示suggest作者使用的是ruby 2.1.5。