Ruby on Rails:删除多个哈希键
Posted
技术标签:
【中文标题】Ruby on Rails:删除多个哈希键【英文标题】:Ruby on Rails: Delete multiple hash keys 【发布时间】:2010-12-06 08:15:25 【问题描述】:我经常发现自己在写这个:
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 API 的丰富性,我怀疑已经有一些方法或习语可以解决这个问题,还有一个猴子补丁没有必要。不过,也许不是。非常感谢所有回答的人! Hash#except 正是我想要的。我不记得它是 Rails 核心扩展,所以当我在 Hash API 中找不到它时,我感到很困惑。 请注意,严格来说答案是Hash#except!
,但Hash#except
才是正确的选择(不要与params
混淆!)。根据经验,除非绝对需要,否则不要就地处理任何对象,副作用可能会产生意想不到的结果。
【参考方案1】:
我猜你不知道 ActiveSupport 添加到 Hash 的 Hash#except 方法。
这将使您的代码简化为:
redirect_to my_path(params.except(:controller, :action, :other_key))
此外,您不必进行猴子补丁,因为 Rails 团队已经为您完成了!
【讨论】:
啊,我知道我以前见过这个,但我不记得在哪里! (因此我的“这感觉不对”的话。)谢谢! 其中一种记录较少的方法。我在提出答案时去寻找类似的东西,但没有看到。 由于某种原因,除了没有工作。但是except!
做到了。 Rails 3.0
Rails 3.2 关于 ActiveRecord 属性,必须使用字符串作为键?即User.attributes.except("id", "created_at", "updated_at")
符号不起作用
除了@house9 提到的内容之外,ActiveRecord attributes
方法返回一个Hash
,其键为String
。那么你必须在.except()
中使用字符串键名。但是,我使用 Hash.symbolize_keys
a la @user.attributes.symbolize_keys.except(:password, :notes)
解决了这个问题 - 使用 symbolize_keys
使其按预期工作【参考方案2】:
虽然使用Hash#except
可以解决您的问题,但请注意它引入了potential security issues。处理来自访问者的任何数据的一个好的经验法则是使用白名单方法。在这种情况下,请改用Hash#slice
。
params.slice!(:param_to_keep_1, :param_to_keep_2)
redirect_to my_path(params)
【讨论】:
感谢您提及有关重定向的安全问题。 请注意:ActiveSupport,而不是 Ruby 本身,提供了 Hash#slice 和#slice! as.rubyonrails.org/classes/ActiveSupport/CoreExtensions/Hash/… 我无法使用 David James 的链接,但这个似乎没问题:api.rubyonrails.org/classes/Hash.html#method-i-slice 未定义方法“切片!”对于:b=>2, :c=>3:Hash
【参考方案3】:
我会对您最初在问题中发布的代码感到非常满意。
[:controller, :action, :other_key].each |k| params.delete(k)
【讨论】:
不修改Hash
这是最好的答案:+1:
我用过这个方法,但是用哈希的名字替换了params,然后就成功了!!哈希值发生了变异。【参考方案4】:
另一种表达 dmathieu 答案的方式可能是
params.delete_if |k,v| [:controller, :action, :other_key].include? k
【讨论】:
【参考方案5】:启动猴子补丁?
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
【讨论】:
猴子补丁是不得已的工具。 猴子补丁替换现有功能是最后的工具。添加新功能的猴子补丁是 Ruby 101。 应该是delete(k)
而不是delete(key)
对于代码维护,非破坏性delete_keys
的实现应该是简单的dup.delete_keys!(*keys)
@Phrogz 根据另一个定义一个并不总是一个坏主意,但为了清楚起见,它只是放在这里展开。【参考方案6】:
我不知道您认为您提出的解决方案有什么问题。我想你想要 Hash 上的 delete_all
方法还是什么?如果是这样,tadman's answer 提供了解决方案。但坦率地说,对于一次性的,我认为您的解决方案非常容易遵循。如果您经常使用它,您可能希望将其包装在一个辅助方法中。
【讨论】:
【参考方案7】:从 Ruby 3.0 开始,直接支持 Hash#except
。这意味着我们不需要主动支持来访问Hash#except
。
来自文档:
Hash#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
【讨论】:
以上是关于Ruby on Rails:删除多个哈希键的主要内容,如果未能解决你的问题,请参考以下文章
如何在 ruby on rails 中集成多个支付网关(多个商家)?
如何在 ruby on rails 中结合救援多个异常?