summaryrefslogtreecommitdiff
path: root/lib/chef/mash.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chef/mash.rb')
-rw-r--r--lib/chef/mash.rb225
1 files changed, 225 insertions, 0 deletions
diff --git a/lib/chef/mash.rb b/lib/chef/mash.rb
new file mode 100644
index 0000000000..edd254cb77
--- /dev/null
+++ b/lib/chef/mash.rb
@@ -0,0 +1,225 @@
+# Copyright (c) 2009 Dan Kubb
+
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+# ---
+# ---
+
+# Some portions of blank.rb and mash.rb are verbatim copies of software
+# licensed under the MIT license. That license is included below:
+
+# Copyright (c) 2005-2008 David Heinemeier Hansson
+
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+# This class has dubious semantics and we only have it so that people can write
+# params[:key] instead of params['key'].
+class Mash < Hash
+
+ # @param constructor<Object>
+ # The default value for the mash. Defaults to an empty hash.
+ #
+ # @details [Alternatives]
+ # If constructor is a Hash, a new mash will be created based on the keys of
+ # the hash and no default value will be set.
+ def initialize(constructor = {})
+ if constructor.is_a?(Hash)
+ super()
+ update(constructor)
+ else
+ super(constructor)
+ end
+ end
+
+ # @param orig<Object> Mash being copied
+ #
+ # @return [Object] A new copied Mash
+ def initialize_copy(orig)
+ super
+ # Handle nested values
+ each do |k,v|
+ if v.kind_of?(Mash) || v.is_a?(Array)
+ self[k] = v.dup
+ end
+ end
+ self
+ end
+
+ # @param key<Object> The default value for the mash. Defaults to nil.
+ #
+ # @details [Alternatives]
+ # If key is a Symbol and it is a key in the mash, then the default value will
+ # be set to the value matching the key.
+ def default(key = nil)
+ if key.is_a?(Symbol) && include?(key = key.to_s)
+ self[key]
+ else
+ super
+ end
+ end
+
+ alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
+ alias_method :regular_update, :update unless method_defined?(:regular_update)
+
+ # @param key<Object> The key to set.
+ # @param value<Object>
+ # The value to set the key to.
+ #
+ # @see Mash#convert_key
+ # @see Mash#convert_value
+ def []=(key, value)
+ regular_writer(convert_key(key), convert_value(value))
+ end
+
+ # @param other_hash<Hash>
+ # A hash to update values in the mash with. The keys and the values will be
+ # converted to Mash format.
+ #
+ # @return [Mash] The updated mash.
+ def update(other_hash)
+ other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) }
+ self
+ end
+
+ alias_method :merge!, :update
+
+ # @param key<Object> The key to check for. This will be run through convert_key.
+ #
+ # @return [Boolean] True if the key exists in the mash.
+ def key?(key)
+ super(convert_key(key))
+ end
+
+ # def include? def has_key? def member?
+ alias_method :include?, :key?
+ alias_method :has_key?, :key?
+ alias_method :member?, :key?
+
+ # @param key<Object> The key to fetch. This will be run through convert_key.
+ # @param *extras<Array> Default value.
+ #
+ # @return [Object] The value at key or the default value.
+ def fetch(key, *extras)
+ super(convert_key(key), *extras)
+ end
+
+ # @param *indices<Array>
+ # The keys to retrieve values for. These will be run through +convert_key+.
+ #
+ # @return [Array] The values at each of the provided keys
+ def values_at(*indices)
+ indices.collect {|key| self[convert_key(key)]}
+ end
+
+ # @param hash<Hash> The hash to merge with the mash.
+ #
+ # @return [Mash] A new mash with the hash values merged in.
+ def merge(hash)
+ self.dup.update(hash)
+ end
+
+ # @param key<Object>
+ # The key to delete from the mash.\
+ def delete(key)
+ super(convert_key(key))
+ end
+
+ # @param *rejected<Array[(String, Symbol)] The mash keys to exclude.
+ #
+ # @return [Mash] A new mash without the selected keys.
+ #
+ # @example
+ # { :one => 1, :two => 2, :three => 3 }.except(:one)
+ # #=> { "two" => 2, "three" => 3 }
+ def except(*keys)
+ super(*keys.map {|k| convert_key(k)})
+ end
+
+ # Used to provide the same interface as Hash.
+ #
+ # @return [Mash] This mash unchanged.
+ def stringify_keys!; self end
+
+ # @return [Hash] The mash as a Hash with symbolized keys.
+ def symbolize_keys
+ h = Hash.new(default)
+ each { |key, val| h[key.to_sym] = val }
+ h
+ end
+
+ # @return [Hash] The mash as a Hash with string keys.
+ def to_hash
+ Hash.new(default).merge(self)
+ end
+
+ # @return [Mash] Convert a Hash into a Mash
+ # The input Hash's default value is maintained
+ def self.from_hash(hash)
+ mash = Mash.new(hash)
+ mash.default = hash.default
+ mash
+ end
+
+ protected
+ # @param key<Object> The key to convert.
+ #
+ # @param [Object]
+ # The converted key. If the key was a symbol, it will be converted to a
+ # string.
+ #
+ # @api private
+ def convert_key(key)
+ key.kind_of?(Symbol) ? key.to_s : key
+ end
+
+ # @param value<Object> The value to convert.
+ #
+ # @return [Object]
+ # The converted value. A Hash or an Array of hashes, will be converted to
+ # their Mash equivalents.
+ #
+ # @api private
+ def convert_value(value)
+ if value.class == Hash
+ Mash.from_hash(value)
+ elsif value.is_a?(Array)
+ value.collect { |e| convert_value(e) }
+ else
+ value
+ end
+ end
+end