Create a gist now

Instantly share code, notes, and snippets.

Hash mix-in to add IndifferentAccess behavior without duplicating a given hash instance
module Hash::Extensions
# Author: Tilo Sloboda , 2012-09-24
# Gist: https://gist.github.com/3778285
#
# Mix-In Module Hash::Extensions::IndifferentAccess
#
# Adds "Hash with Indifferent Access" behavior to an existing Hash
# without creating a copy of that Hash.
#
# Limitation: does not work for embedded hashes.
#
# Purpose:
# When passing a parameter hash to Resque/Redis, the hash keys
# get persisted as Strings, not Symbols. including this mix-in
# into the param hash, allows to access the very same hash with symbols.
#
# e.g.:
# def perform(params_hash)
# class << params_hash
# include Hash::Extensions::IndifferentAccess # add behavior without creating duplicate
# end
# params.create_symbols_only(true) # if new keys should be created as symbols
#
# # ... Rescue Worker Code
#
# end
module IndifferentAccess
def self.included(base)
base.class_eval do
alias_method :regular_write, :[]=
%w(default update fetch delete key? values_at).each do |m|
alias_method "regular_#{m}", m
end
# forces new hash keys to always be symbols; default: false
def create_symbols_only( boolean=true )
@__CREATE_SYMBOLS_ONLY = boolean
end
def [](key)
if self.include?(key)
self.regular_fetch(key) # regular reader
else
if key.class == Symbol && self.include?(key.to_s)
return self.regular_fetch( key.to_s )
elsif key.class == String && self.include?(key.to_sym)
return self.regular_fetch( key.to_sym )
else
return nil # the key wasn't defined
end
end
end
def []=(key,value)
if self.include?(key)
self.regular_write(key , value)
else
if key.class == Symbol && self.include?(key.to_s)
self.regular_write(key.to_s , value)
elsif key.class == String && self.include?(key.to_sym)
self.regular_write(key.to_sym , value)
else # new parameter which was not there before
if @__CREATE_SYMBOLS_ONLY
self.regular_write(key.to_sym, value)
else
self.regular_write(key, value) # whatever was handed in
end
end
end
end
end # end of class eval
end # end of included()
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment