Ruby on Rails: Delete multiple hash keys

Ruby on-RailsRuby

Ruby on-Rails Problem Overview


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?

Ruby on-Rails Solutions


Solution 1 - Ruby on-Rails

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!

Solution 2 - Ruby on-Rails

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)

Solution 3 - Ruby on-Rails

I'd be completely happy with the code you originally posted in your question.

[:controller, :action, :other_key].each { |k| params.delete(k) }

Solution 4 - Ruby on-Rails

Another way to phrase dmathieu's answer might be

params.delete_if { |k,v| [:controller, :action, :other_key].include? k }

Solution 5 - Ruby on-Rails

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

Solution 6 - Ruby on-Rails

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.

Solution 7 - Ruby on-Rails

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMark WestlingView Question on Stackoverflow
Solution 1 - Ruby on-RailsBen CrouseView Answer on Stackoverflow
Solution 2 - Ruby on-Railsuser190125View Answer on Stackoverflow
Solution 3 - Ruby on-RailsBob AmanView Answer on Stackoverflow
Solution 4 - Ruby on-RailsMike SeplowitzView Answer on Stackoverflow
Solution 5 - Ruby on-RailstadmanView Answer on Stackoverflow
Solution 6 - Ruby on-RailsPestoView Answer on Stackoverflow
Solution 7 - Ruby on-Railsthe_spectatorView Answer on Stackoverflow