Ruby on Rails: Delete Multiple Hash Keys

Ruby on Rails: Delete multiple hash keys

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!

Deleting multiple key and value pairs from hash in Rails


number.delete "A"
number.delete "B"
number.delete "C"

Or, less performant but more terse:

number.reject! {|k, v| %w"A B C".include? k }

Delete array of keys in Ruby Hash

You can iterate over an array of keys and delete everyone of them:

[key1, key2, key3].each { |k| some_hash.delete k }

Can't remember any better solution.

How to remove a key from Hash and get the remaining hash in Ruby/Rails?

Rails has an except/except! method that returns the hash with those keys removed. If you're already using Rails, there's no sense in creating your own version of this.

class Hash
# Returns a hash that includes everything but the given keys.
# hash = { a: true, b: false, c: nil}
# hash.except(:c) # => { a: true, b: false}
# hash # => { a: true, b: false, c: nil}
#
# This is useful for limiting a set of parameters to everything but a few known toggles:
# @person.update(params[:person].except(:admin))
def except(*keys)
dup.except!(*keys)
end

# Replaces the hash without the given keys.
# hash = { a: true, b: false, c: nil}
# hash.except!(:c) # => { a: true, b: false}
# hash # => { a: true, b: false }
def except!(*keys)
keys.each { |key| delete(key) }
self
end
end

Adding multiple values to a key in Ruby as well as delete just one value associated


Use a Nil Guard

You need to guard against missing keys and values in your Hash. There are a number of ways to do this, but on any recent Ruby the &. operator ensures that a method doesn't raise an exception if called on nil. The following works fine:

h = {
a: [1, 3, 4],
b: [3, 6],
c: [4, 8, 87]
}

h[:c]&.delete 87; h
#=> {:a=>[1, 3, 4], :b=>[3, 6], :c=>[4, 8]}

h[:x]&.delete 101; h
#=> {:a=>[1, 3, 4], :b=>[3, 6], :c=>[4, 8]}

Updating multiple hash keys after merging values

You can't switch out one object for another unless you have some kind of a wrapper. Unless performance matters a lot, the easiest wrappers to use are proxy objects, because you don't need to unwrap them: they transparently behave exactly like the wrapped object.

class ProxyObject
# thanks to https://alisdair.mcdiarmid.org/invisible-proxies-with-ruby/
instance_methods.each do |m|
undef_method(m) unless m =~ /(^__|^nil\?$|^send$|^object_id$)/
end

attr_accessor :target

def initialize(target)
@target = target
end

def respond_to?(symbol, include_priv=false)
@target.respond_to?(symbol, include_priv)
end

private def method_missing(method, *args, &block)
@target.send(method, *args, &block)
end
end

a = 1
b = 10
a_proxy = ProxyObject.new(a)
b_proxy = ProxyObject.new(b)
a_proxy.class # verify how well they masquerade
# => Integer
hash = 10.times.map { |i| [i + 1, i < 5 ? a_proxy : b_proxy] }.to_h
# => {1=>1, 2=>1, 3=>1, 4=>1, 5=>1, 6=>10, 7=>10, 8=>10, 9=>10, 10=>10}
hash.values.sum() # confirm it behaves exactly like a number
# => 55
b_proxy.target = a_proxy.target # switch reference
hash
# => {1=>1, 2=>1, 3=>1, 4=>1, 5=>1, 6=>1, 7=>1, 8=>1, 9=>1, 10=>1}
hash.values.sum() # confirm the reference is changed
# => 10


Related Topics



Leave a reply



Submit