Reputation: 5974
I often find myself writing this:
params.delete(:controller)
params.delete(:action)
params.delete(:other_key)
redirect_to my_path(params)
The trail of deletes doesn't feel right and neither does:
[:controller, :action, :other_key].each do |k|
params.delete(k)
end
Is there anything simpler and cleaner?
Upvotes: 161
Views: 83626
Reputation: 1603
Starting from Ruby 3.0, Hash#except
is supported directly. This means we would not need activesupport to access Hash#except
.
From documentation:
Hash#except(*keys) → hash
This method returns a new hash, which includes everything from the original hash except the given keys.
example:
h = { a: 100, b: 200, c: 300, d: 400 }
h.except(:a, :d) #=> {:b=>200, :c=>300}
Reference:
https://docs.ruby-lang.org/en/3.0.0/Hash.html#method-i-except
Upvotes: 9
Reputation:
While using Hash#except
handles your problem, be aware that it introduces potential security issues. A good rule of thumb for handling any data from visitors is to use a whitelist approach. In this case, using Hash#slice
instead.
params.slice!(:param_to_keep_1, :param_to_keep_2)
redirect_to my_path(params)
Upvotes: 46
Reputation: 8348
I'm guessing you're unaware of the Hash#except method ActiveSupport adds to Hash.
It would allow your code to be simplified to:
redirect_to my_path(params.except(:controller, :action, :other_key))
Also, you wouldn't have to monkey patch, since the Rails team did it for you!
Upvotes: 238
Reputation: 211540
Fire up a monkey patch?
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
Upvotes: 7
Reputation: 10375
Another way to phrase dmathieu's answer might be
params.delete_if { |k,v| [:controller, :action, :other_key].include? k }
Upvotes: 15
Reputation: 33239
I'd be completely happy with the code you originally posted in your question.
[:controller, :action, :other_key].each { |k| params.delete(k) }
Upvotes: 28
Reputation: 23880
I don't know what you think is wrong with your proposed solution. I suppose you want a delete_all
method on Hash or something? If so, tadman's answer provides the solution. But frankly, for a one-off, I think your solution is extremely easy to follow. If you're using this frequently, you might want to wrap it up in a helper method.
Upvotes: 2