class Hash

def _deep_transform_keys_in_object(object, &block)

support methods for deep transforming nested hashes and arrays
def _deep_transform_keys_in_object(object, &block)
  case object
  when Hash
    object.each_with_object({}) do |(key, value), result|
      result[yield(key)] = _deep_transform_keys_in_object(value, &block)
    end
  when Array
    object.map {|e| _deep_transform_keys_in_object(e, &block) }
  else
    object
  end
end

def _deep_transform_keys_in_object!(object, &block)

def _deep_transform_keys_in_object!(object, &block)
  case object
  when Hash
    object.keys.each do |key|
      value = object.delete(key)
      object[yield(key)] = _deep_transform_keys_in_object!(value, &block)
    end
    object
  when Array
    object.map! {|e| _deep_transform_keys_in_object!(e, &block)}
  else
    object
  end
end

def as_json(options = nil) #:nodoc:

:nodoc:
def as_json(options = nil) #:nodoc:
  # create a subset of the hash by applying :only or :except
  subset = if options
    if attrs = options[:only]
      slice(*Array(attrs))
    elsif attrs = options[:except]
      except(*Array(attrs))
    else
      self
    end
  else
    self
  end
  # use encoder as a proxy to call as_json on all values in the subset, to protect from circular references
  encoder = options && options[:encoder] || ActiveSupport::JSON::Encoding::Encoder.new(options)
  Hash[subset.map { |k, v| [k.to_s, encoder.as_json(v, options)] }]
end

def assert_valid_keys(*valid_keys)

{ name: 'Rob', age: '28' }.assert_valid_keys(:name, :age) # => passes, raises nothing
{ name: 'Rob', age: '28' }.assert_valid_keys('name', 'age') # => raises "ArgumentError: Unknown key: name"
{ name: 'Rob', years: '28' }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key: years"

use strings for keys but assert symbols as keys, this will fail.
on a mismatch. Note that keys are NOT treated indifferently, meaning if you
Validate all keys in a hash match *valid_keys, raising ArgumentError
def assert_valid_keys(*valid_keys)
  valid_keys.flatten!
  each_key do |k|
    raise ArgumentError.new("Unknown key: #{k}") unless valid_keys.include?(k)
  end
end

def deep_dup

dup[:a][:c] #=> "c"
hash[:a][:c] #=> nil

dup[:a][:c] = 'c'
dup = hash.deep_dup
hash = { a: { b: 'b' } }

Returns a deep copy of hash.
def deep_dup
  each_with_object(dup) do |(key, value), hash|
    hash[key.deep_dup] = value.deep_dup
  end
end

def deep_merge(other_hash, &block)

# => { a: 100, b: 450, c: { c1: 300 } }
h1.deep_merge(h2) { |key, this_val, other_val| this_val + other_val }
h2 = { b: 250, c: { c1: 200 } }
h1 = { a: 100, b: 200, c: { c1: 100 } }

to merge values:
Like with Hash#merge in the standard library, a block can be provided

h1.deep_merge(h2) #=> { a: false, b: { c: [1, 2, 3], x: [3, 4, 5] } }

h2 = { a: false, b: { x: [3, 4, 5] } }
h1 = { a: true, b: { c: [1, 2, 3] } }

Returns a new hash with +self+ and +other_hash+ merged recursively.
def deep_merge(other_hash, &block)
  dup.deep_merge!(other_hash, &block)
end

def deep_merge!(other_hash, &block)

Same as +deep_merge+, but modifies +self+.
def deep_merge!(other_hash, &block)
  other_hash.each_pair do |current_key, other_value|
    this_value = self[current_key]
    self[current_key] = if this_value.is_a?(Hash) && other_value.is_a?(Hash)
      this_value.deep_merge(other_value, &block)
    else
      if block_given? && key?(current_key)
        block.call(current_key, this_value, other_value)
      else
        other_value
      end
    end
  end
  self
end

def deep_stringify_keys

# => { "person" => { "name" => "Rob", "age" => "28" } }
hash.deep_stringify_keys

hash = { person: { name: 'Rob', age: '28' } }

nested hashes and arrays.
This includes the keys from the root hash and from all
Return a new hash with all keys converted to strings.
def deep_stringify_keys
  deep_transform_keys{ |key| key.to_s }
end

def deep_stringify_keys!

nested hashes and arrays.
This includes the keys from the root hash and from all
Destructively convert all keys to strings.
def deep_stringify_keys!
  deep_transform_keys!{ |key| key.to_s }
end

def deep_symbolize_keys

# => { person: { name: "Rob", age: "28" } }
hash.deep_symbolize_keys

hash = { 'person' => { 'name' => 'Rob', 'age' => '28' } }

and from all nested hashes and arrays.
they respond to +to_sym+. This includes the keys from the root hash
Return a new hash with all keys converted to symbols, as long as
def deep_symbolize_keys
  deep_transform_keys{ |key| key.to_sym rescue key }
end

def deep_symbolize_keys!

nested hashes and arrays.
to +to_sym+. This includes the keys from the root hash and from all
Destructively convert all keys to symbols, as long as they respond
def deep_symbolize_keys!
  deep_transform_keys!{ |key| key.to_sym rescue key }
end

def deep_transform_keys(&block)

# => { "PERSON" => { "NAME" => "Rob", "AGE" => "28" } }
hash.deep_transform_keys{ |key| key.to_s.upcase }

hash = { person: { name: 'Rob', age: '28' } }

nested hashes and arrays.
This includes the keys from the root hash and from all
Return a new hash with all keys converted by the block operation.
def deep_transform_keys(&block)
  _deep_transform_keys_in_object(self, &block)
end

def deep_transform_keys!(&block)

nested hashes and arrays.
This includes the keys from the root hash and from all
Destructively convert all keys by using the block operation.
def deep_transform_keys!(&block)
  _deep_transform_keys_in_object!(self, &block)
end

def diff(other)

{1 => 2, 3 => 4}.diff(1 => 2) # => {3 => 4}
{}.diff(1 => 2) # => {1 => 2}
{1 => 2}.diff(1 => 3) # => {1 => 2}
{1 => 2}.diff(1 => 2) # => {}

Returns a hash that represents the difference between two hashes.
def diff(other)
  ActiveSupport::Deprecation.warn "Hash#diff is no longer used inside of Rails, and is being deprecated with no replacement. If you're using it to compare hashes for the purpose of testing, please use MiniTest's assert_equal instead."
  dup.
    delete_if { |k, v| other[k] == v }.
    merge!(other.dup.delete_if { |k, v| has_key?(k) })
end

def encode_json(encoder) #:nodoc:

:nodoc:
def encode_json(encoder) #:nodoc:
  # values are encoded with use_options = false, because we don't want hash representations from ActiveModel to be
  # processed once again with as_json with options, as this could cause unexpected results (i.e. missing fields);
  # on the other hand, we need to run as_json on the elements, because the model representation may contain fields
  # like Time/Date in their original (not jsonified) form, etc.
  "{#{map { |k,v| "#{encoder.encode(k.to_s)}:#{encoder.encode(v, false)}" } * ','}}"
end

def except(*keys)

@person.update(params[:person].except(:admin))

limiting a set of parameters to everything but a few known toggles:
Return a hash that includes everything but the given keys. This is useful for
def except(*keys)
  dup.except!(*keys)
end

def except!(*keys)

Replaces the hash without the given keys.
def except!(*keys)
  keys.each { |key| delete(key) }
  self
end

def extract!(*keys)

{ a: 1, b: 2 }.extract!(:a, :x) # => {:a=>1}
{ a: 1, b: 2, c: 3, d: 4 }.extract!(:a, :b) # => {:a=>1, :b=>2}

Removes and returns the key/value pairs matching the given keys.
def extract!(*keys)
  keys.each_with_object(self.class.new) { |key, result| result[key] = delete(key) if has_key?(key) }
end

def extractable_options?

the Array when it is the last element of the Array.
is extractable, Array#extract_options! pops it from
true to declare themselves as extractable. If a Hash
Subclasses of Hash may implement this method and return
By default, only instances of Hash itself are extractable.
def extractable_options?
  instance_of?(Hash)
end

def from_trusted_xml(xml)

Builds a Hash from XML just like Hash.from_xml, but also allows Symbol and YAML.
def from_trusted_xml(xml)
  from_xml xml, []
end

def from_xml(xml, disallowed_types = nil)

type="symbol". Use Hash.from_trusted_xml to parse this XML.
DisallowedType is raise if the XML contains attributes with type="yaml" or

# => {"hash"=>{"foo"=>1, "bar"=>2}}
hash = Hash.from_xml(xml)

XML

2
1


xml = <<-XML

its content
Returns a Hash containing a collection of pairs when the key is the node name and the value is
def from_xml(xml, disallowed_types = nil)
  ActiveSupport::XMLConverter.new(xml, disallowed_types).to_h
end

def reverse_merge(other_hash)

with default values.
This is particularly useful for initializing an options hash

options = { size: 25, velocity: 10 }.merge(options)

is equivalent to

options = options.reverse_merge(size: 25, velocity: 10)

Merges the caller into +other_hash+. For example,
def reverse_merge(other_hash)
  other_hash.merge(self)
end

def reverse_merge!(other_hash)

Destructive +reverse_merge+.
def reverse_merge!(other_hash)
  # right wins if there is no left
  merge!( other_hash ){|key,left,right| left }
end

def slice(*keys)

search(options.slice(*valid_keys))
valid_keys = [:mass, :velocity, :time]

If you have an array of keys you want to limit to, you should splat them:

search(options.slice(:mass, :velocity, :time))

end
criteria.assert_valid_keys(:mass, :velocity, :time)
def search(criteria = {})

limiting an options hash to valid keys before passing to a method:
Slice a hash to include only the given keys. This is useful for
def slice(*keys)
  keys.map! { |key| convert_key(key) } if respond_to?(:convert_key, true)
  keys.each_with_object(self.class.new) { |k, hash| hash[k] = self[k] if has_key?(k) }
end

def slice!(*keys)

# => {:c=>3, :d=>4}
{ a: 1, b: 2, c: 3, d: 4 }.slice!(:a, :b)

Returns a hash containing the removed key/value pairs.
Replaces the hash with only the given keys.
def slice!(*keys)
  keys.map! { |key| convert_key(key) } if respond_to?(:convert_key, true)
  omit = slice(*self.keys - keys)
  hash = slice(*keys)
  hash.default      = default
  hash.default_proc = default_proc if default_proc
  replace(hash)
  omit
end

def stringify_keys

#=> { "name" => "Rob", "age" => "28" }
hash.stringify_keys

hash = { name: 'Rob', age: '28' }

Return a new hash with all keys converted to strings.
def stringify_keys
  transform_keys{ |key| key.to_s }
end

def stringify_keys!

+stringify_keys+, but modifies +self+.
Destructively convert all keys to strings. Same as
def stringify_keys!
  transform_keys!{ |key| key.to_s }
end

def symbolize_keys

#=> { name: "Rob", age: "28" }
hash.symbolize_keys

hash = { 'name' => 'Rob', 'age' => '28' }

they respond to +to_sym+.
Return a new hash with all keys converted to symbols, as long as
def symbolize_keys
  transform_keys{ |key| key.to_sym rescue key }
end

def symbolize_keys!

to +to_sym+. Same as +symbolize_keys+, but modifies +self+.
Destructively convert all keys to symbols, as long as they respond
def symbolize_keys!
  transform_keys!{ |key| key.to_sym rescue key }
end

def to_query(namespace = nil)

This method is also aliased as +to_param+.

are sorted lexicographically in ascending order.
The string pairs "key=value" that conform the query string

# => "user[name]=David&user[nationality]=Danish"
{name: 'David', nationality: 'Danish'}.to_query('user')

An optional namespace can be passed to enclose the param names:

# => "name=David&nationality=Danish"
{name: 'David', nationality: 'Danish'}.to_query

query string:
Returns a string representation of the receiver suitable for use as a URL
def to_query(namespace = nil)
  collect do |key, value|
    value.to_query(namespace ? "#{namespace}[#{key}]" : key)
  end.sort * '&'
end

def to_xml(options = {})

options like :dasherize and friends, they are forwarded to the builder.
configure your own builder with the :builder option. The method also accepts
The default XML builder is a fresh instance of Builder::XmlMarkup. You can

By default the root node is "hash", but that's configurable via the :root option.

}
"Time" => "dateTime"
"DateTime" => "dateTime",
"Date" => "date",
"FalseClass" => "boolean",
"TrueClass" => "boolean",
"Float" => "float",
"BigDecimal" => "decimal",
"Bignum" => "integer",
"Fixnum" => "integer",
"Symbol" => "symbol",
XML_TYPE_NAMES = {

added as well according to the following mapping:
Unless the option :skip_types exists and is true, an attribute "type" is
+value+ as text node. If +value+ is +nil+ an attribute "nil" set to "true" is added.
* Otherwise, a node with +key+ as tag is created with a string representation of

# => "fooing!"
{ foo: Foo.new }.to_xml(skip_instruct: true)

end
end
options[:builder].bar 'fooing!'
def to_xml(options)
class Foo

* If +value+ responds to +to_xml+ the method is invoked with +key+ as :root.

# => "foo"
'foo'.to_xml(lambda { |options, key| options[:builder].b(key) })

callable can add nodes by using options[:builder].
with +key+ as :root, and +key+ singularized as second argument. The
on the arity, the callable is invoked with the +options+ hash as first argument
* If +value+ is a callable object it must expect one or two arguments. Depending

and +key+ singularized as :children.
* If +value+ is an array there's a recursive call with +key+ as :root,

* If +value+ is a hash there's a recursive call with +key+ as :root.

the _values_. Given a pair +key+, +value+:
To do so, the method loops over the pairs and builds nodes that depend on

#
# 2
# 1
#
#
# =>
{'foo' => 1, 'bar' => 2}.to_xml

Returns a string containing an XML representation of its receiver:
def to_xml(options = {})
  require 'active_support/builder' unless defined?(Builder)
  options = options.dup
  options[:indent]  ||= 2
  options[:root]    ||= 'hash'
  options[:builder] ||= Builder::XmlMarkup.new(indent: options[:indent])
  builder = options[:builder]
  builder.instruct! unless options.delete(:skip_instruct)
  root = ActiveSupport::XmlMini.rename_key(options[:root].to_s, options)
  builder.tag!(root) do
    each { |key, value| ActiveSupport::XmlMini.to_tag(key, value, options) }
    yield builder if block_given?
  end
end

def transform_keys

# => { "NAME" => "Rob", "AGE" => "28" }
hash.transform_keys{ |key| key.to_s.upcase }

hash = { name: 'Rob', age: '28' }

Return a new hash with all keys converted using the block operation.
def transform_keys
  result = {}
  each_key do |key|
    result[yield(key)] = self[key]
  end
  result
end

def transform_keys!

Same as transform_keys but modifies +self+.
Destructively convert all keys using the block operations.
def transform_keys!
  keys.each do |key|
    self[yield(key)] = delete(key)
  end
  self
end

def with_indifferent_access

{ a: 1 }.with_indifferent_access['a'] # => 1

Returns an ActiveSupport::HashWithIndifferentAccess out of its receiver:
def with_indifferent_access
  ActiveSupport::HashWithIndifferentAccess.new_from_hash_copying_default(self)
end