我经常发现自己在写这个:
params.delete(:controller)
params.delete(:action)
params.delete(:other_key)
redirect_to my_path(params)
删除的痕迹感觉不对,也不对:
[:controller, :action, :other_key].each do |k|
params.delete(k)
end
有什么更简单更干净的吗?
Hash#except!
但 Hash#except
是要走的路(不要与 params
混淆!)。根据经验,除非绝对需要,否则不要就地处理任何对象,副作用可能会产生意想不到的结果。
我猜您不知道 ActiveSupport 添加到 Hash 的 Hash#except 方法。
它可以让您的代码简化为:
redirect_to my_path(params.except(:controller, :action, :other_key))
此外,您不必修改补丁,因为 Rails 团队已经为您完成了!
在使用 Hash#except
处理您的问题时,请注意它引入了 potential security issues。处理来自访问者的任何数据的一个好的经验法则是使用白名单方法。在这种情况下,请改用 Hash#slice
。
params.slice!(:param_to_keep_1, :param_to_keep_2)
redirect_to my_path(params)
{:b=>2, :c=>3}:Hash
我会对您最初在问题中发布的代码感到非常满意。
[:controller, :action, :other_key].each { |k| params.delete(k) }
Hash
这是最好的答案:+1:
表达 dmathieu 答案的另一种方式可能是
params.delete_if { |k,v| [:controller, :action, :other_key].include? k }
启动猴子补丁?
class Hash
def delete_keys!(*keys)
keys.flatten.each do |k|
delete(k)
end
self
end
def delete_keys(*keys)
_dup = dup
keys.flatten.each do |k|
_dup.delete(k)
end
_dup
end
end
delete(k)
而不是 delete(key)
delete_keys
的实现应该只是 dup.delete_keys!(*keys)
我不知道您认为您提出的解决方案有什么问题。我想你想要一个关于 Hash 或什么的 delete_all
方法?如果是这样,tadman's answer 提供了解决方案。但坦率地说,对于一次性的,我认为您的解决方案非常容易遵循。如果您经常使用它,您可能希望将它包装在一个辅助方法中。
从 Ruby 3.0 开始,直接支持 Hash#except
。这意味着我们不需要主动支持来访问 Hash#except
。
从文档:
哈希#except(*keys) → 哈希
此方法返回一个新哈希,其中包括原始哈希中除给定键之外的所有内容。
例子:
h = { a: 100, b: 200, c: 300, d: 400 }
h.except(:a, :d) #=> {:b=>200, :c=>300}
参考:
https://docs.ruby-lang.org/en/3.0.0/Hash.html#method-i-except
不定期副业成功案例分享
except!
做到了。导轨 3.0User.attributes.except("id", "created_at", "updated_at")
符号不起作用attributes
方法返回一个Hash
,其键为String
。因此,您必须在.except()
中使用字符串键名。但是,我使用Hash.symbolize_keys
a la@user.attributes.symbolize_keys.except(:password, :notes)
解决了这个问题 - 使用symbolize_keys
使其按预期工作