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