ruby-on-rails - HashWithIndifferentAccess 不适用于 Rails 5 中的 % 格式运算符
问题描述
Ruby 字符串的方法%
允许用给定哈希的值替换名称占位符:"Hello %{name}" % {name: "World"}
结果为"Hello World"
.
问题是它不适用于HashWithIndifferentAccess
参数。在 Rails 5 中,这段代码会引发异常:
2.3.8 :001 > "%{a}" % {"a" => 1}.with_indifferent_access
KeyError: key{a} not found
from (irb):1:in `%'
from (irb):1
同样有趣的是,相同的代码在 Rails 4 中运行良好,但在 Rails 5 中却不行
有没有办法修复它(可能是一些猴子补丁ActiveSupport::HashWithIndifferentAccess
)并理解为什么%
(以及sprintf
)的行为发生了变化?
解决方案
ActiveSupport::HashWithIndifferentAccess
这主要是因为只要 Rails 一直在发展和default
方法(不要与 Hash#default 混淆) ,通过不同版本引入的更改。
如果您在 Rails 4 版本的 ActiveSupport::HashWithIndifferentAccess 中看到默认方法如下所示:
def default(key = nil)
if key.is_a?(Symbol) && include?(key = key.to_s)
self[key]
else
super
end
end
很明显,它在被调用时接收一个键,检查它的类型以及是否包含在哈希(self)中作为它的键之一,返回它的值,否则调用 super。
在较新的版本中(较新,因为您的示例在 Rails 4+ 版本中不起作用)它看起来像:
def default(*args)
super(*args.map { |arg| convert_key(arg) })
end
def convert_key(key) # :doc:
key.kind_of?(Symbol) ? key.to_s : key
end
如果它是符号或返回相同的元素,则在调用 String 时尝试从传递给默认值的参数中返回每个元素。
在您的示例中,这将返回 nil for default
,这解释了您遇到的 KeyError 错误。
行为的错误或差异不%
在于引入的更改。
推荐阅读
- python - 从 Python 中的字典列表构建深度嵌套字典的最有效方法
- docker - 如何进行 Docker 镜像的确定性构建?
- python - Google 表格样式(仅第一行粗体字)
- angular - 从服务器获取数据并将其传递给 Angular 页面
- php - 在 Woocommerce 中获取和使用用户组名称
- swift - CollectionView 单元格上的 AttributedString 未显示字符串值
- javascript - 如何从数组中检索活动项目列表?
- python - 通过“n”生成网格/嵌套列表“n”
- matlab - LaTeX 解释器,但 Matlab 图形上的无衬线字体
- php - Laravel Nova 和 Dingo API 路由冲突