Class: Hashie::Mash
- Defined in:
- lib/hashie/mash.rb
Overview
Mash allows you to create pseudo-objects that have method-like accessors for hash keys. This is useful for such implementations as an API-accessing library that wants to fake robust objects without the overhead of actually doing so. Think of it as OpenStruct with some additional goodies.
A Mash will look at the methods you pass it and perform operations based on the following rules:
- No punctuation: Returns the value of the hash for that key, or nil if none exists.
- Assignment (=): Sets the attribute of the given method name.
- Existence (?): Returns true or false depending on whether that key has been set.
- Bang (!): Forces the existence of this key, used for deep Mashes. Think of it as "touch" for mashes.
- Under Bang (_): Like Bang, but returns a new Mash rather than creating a key. Used to test existance in deep Mashes.
== Basic Example
mash = Mash.new mash.name? # => false mash.name = "Bob" mash.name # => "Bob" mash.name? # => true
== Hash Conversion Example
hash = => {:b => 23, :d => {:e => "abc"}, :f => [=> 44, :h => 29, 12]} mash = Mash.new(hash) mash.a.b # => 23 mash.a.d.e # => "abc" mash.f.first.g # => 44 mash.f.last # => 12
== Bang Example
mash = Mash.new
mash.author # => nil
mash.author! # =>
mash = Mash.new
mash.author!.name = "Michael Bleigh"
mash.author # =>
== Under Bang Example
mash = Mash.new
mash.author # => nil
mash.author_ # =>
mash = Mash.new
mash.author_.name = "Michael Bleigh" (assigned to temp object)
mash.author # =>
Defined Under Namespace
Classes: CannotDisableMashWarnings
Constant Summary collapse
- ALLOWED_SUFFIXES =
%w(? ! = _)
Class Method Summary collapse
-
.disable_warnings ⇒ void
Disable the logging of warnings based on keys conflicting keys/methods.
-
.disable_warnings? ⇒ Boolean
Checks whether this class disables warnings for conflicting keys/methods.
-
.inherited(subclass) ⇒ void
Inheritance hook that sets class configuration when inherited.
- .load(path, options = {}) ⇒ Object
Instance Method Summary collapse
-
#assign_property(name, value) ⇒ Object
Assigns a value to a key.
-
#custom_reader(key) {|value| ... } ⇒ Object
(also: #[])
Retrieves an attribute set in the Mash.
-
#custom_writer(key, value, convert = true) ⇒ Object
(also: #[]=)
Sets an attribute in the Mash.
-
#deep_merge(other_hash, &blk) ⇒ Object
(also: #merge)
Performs a deep_update on a duplicate of the current mash.
-
#deep_update(other_hash, &blk) ⇒ Object
(also: #deep_merge!, #update)
Recursively merges this mash with the passed in hash, merging each hash in the hierarchy.
- #delete(key) ⇒ Object
-
#dup ⇒ Object
Duplicates the current mash as a new mash.
-
#extractable_options? ⇒ Boolean
play nice with ActiveSupport Array#extract_options!.
- #fetch(key, *args) ⇒ Object
-
#initialize(source_hash = nil, default = nil, &blk) ⇒ Mash
constructor
If you pass in an existing hash, it will convert it to a Mash including recursively descending into arrays and hashes, converting them as well.
-
#initializing_reader(key) ⇒ Object
This is the bang method reader, it will return a new Mash if there isn't a value already assigned to the key requested.
- #key?(key) ⇒ Boolean (also: #has_key?, #include?, #member?)
- #method_missing(method_name, *args, &blk) ⇒ Object
- #prefix_method?(method_name) ⇒ Boolean
- #regular_dup ⇒ Object
- #replace(other_hash) ⇒ Object
- #respond_to_missing?(method_name, *args) ⇒ Boolean
-
#reverse_merge(other_hash) ⇒ Object
another ActiveSupport method, see issue #270.
-
#shallow_merge(other_hash) ⇒ Object
Performs a shallow_update on a duplicate of the current mash.
-
#shallow_update(other_hash) ⇒ Object
Merges (non-recursively) the hash from the argument, changing the receiving hash.
- #to_module(mash_method_name = :settings) ⇒ Object
-
#underbang_reader(key) ⇒ Object
This is the under bang method reader, it will return a temporary new Mash if there isn't a value already assigned to the key requested.
- #values_at(*keys) ⇒ Object
Methods included from Extensions::RubyVersionCheck
Methods included from Extensions::PrettyInspect
Methods inherited from Hash
Methods included from Extensions::StringifyKeys
#stringify_keys, #stringify_keys!
Methods included from Extensions::StringifyKeys::ClassMethods
#stringify_keys, #stringify_keys!, #stringify_keys_recursively!
Constructor Details
#initialize(source_hash = nil, default = nil, &blk) ⇒ Mash
If you pass in an existing hash, it will convert it to a Mash including recursively descending into arrays and hashes, converting them as well.
123 124 125 126 |
# File 'lib/hashie/mash.rb', line 123 def initialize(source_hash = nil, default = nil, &blk) deep_update(source_hash) if source_hash default ? super(default) : super(&blk) end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method_name, *args, &blk) ⇒ Object
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 |
# File 'lib/hashie/mash.rb', line 265 def method_missing(method_name, *args, &blk) return self.[](method_name, &blk) if key?(method_name) name, suffix = method_name_and_suffix(method_name) case suffix when '='.freeze assign_property(name, args.first) when '?'.freeze !!self[name] when '!'.freeze initializing_reader(name) when '_'.freeze underbang_reader(name) else self[method_name] end end |
Class Method Details
.disable_warnings ⇒ void
This method returns an undefined value.
Disable the logging of warnings based on keys conflicting keys/methods
76 77 78 79 |
# File 'lib/hashie/mash.rb', line 76 def self.disable_warnings fail CannotDisableMashWarnings if self == Hashie::Mash @disable_warnings = true end |
.disable_warnings? ⇒ Boolean
Checks whether this class disables warnings for conflicting keys/methods
85 86 87 |
# File 'lib/hashie/mash.rb', line 85 def self.disable_warnings? !!@disable_warnings end |
.inherited(subclass) ⇒ void
This method returns an undefined value.
Inheritance hook that sets class configuration when inherited.
93 94 95 96 |
# File 'lib/hashie/mash.rb', line 93 def self.inherited(subclass) super subclass.disable_warnings if disable_warnings? end |
.load(path, options = {}) ⇒ Object
98 99 100 101 102 103 104 105 106 |
# File 'lib/hashie/mash.rb', line 98 def self.load(path, = {}) @_mashes ||= new return @_mashes[path] if @_mashes.key?(path) fail ArgumentError, "The following file doesn't exist: #{path}" unless File.file?(path) parser = .fetch(:parser) { Hashie::Extensions::Parsers::YamlErbParser } @_mashes[path] = new(parser.perform(path)).freeze end |
Instance Method Details
#assign_property(name, value) ⇒ Object
Assigns a value to a key
226 227 228 |
# File 'lib/hashie/mash.rb', line 226 def assign_property(name, value) self[name] = value end |
#custom_reader(key) {|value| ... } ⇒ Object Also known as: []
Retrieves an attribute set in the Mash. Will convert any key passed in to a string before retrieving.
135 136 137 138 139 140 |
# File 'lib/hashie/mash.rb', line 135 def custom_reader(key) default_proc.call(self, key) if default_proc && !key?(key) value = regular_reader(convert_key(key)) yield value if block_given? value end |
#custom_writer(key, value, convert = true) ⇒ Object Also known as: []=
Sets an attribute in the Mash. Key will be converted to a string before it is set, and Hashes will be converted into Mashes for nesting purposes.
145 146 147 148 149 150 |
# File 'lib/hashie/mash.rb', line 145 def custom_writer(key, value, convert = true) #:nodoc: key_as_symbol = (key = convert_key(key)).to_sym (key_as_symbol) if respond_to?(key_as_symbol) regular_writer(key, convert ? convert_value(value) : value) end |
#deep_merge(other_hash, &blk) ⇒ Object Also known as: merge
Performs a deep_update on a duplicate of the current mash.
201 202 203 |
# File 'lib/hashie/mash.rb', line 201 def deep_merge(other_hash, &blk) dup.deep_update(other_hash, &blk) end |
#deep_update(other_hash, &blk) ⇒ Object Also known as: deep_merge!, update
Recursively merges this mash with the passed in hash, merging each hash in the hierarchy.
208 209 210 211 212 213 214 215 216 217 218 219 220 |
# File 'lib/hashie/mash.rb', line 208 def deep_update(other_hash, &blk) other_hash.each_pair do |k, v| key = convert_key(k) if regular_reader(key).is_a?(Mash) && v.is_a?(::Hash) custom_reader(key).deep_update(v, &blk) else value = convert_value(v, true) value = convert_value(blk.call(key, self[k], value), true) if blk && self.key?(k) custom_writer(key, value, false) end end self end |
#delete(key) ⇒ Object
178 179 180 |
# File 'lib/hashie/mash.rb', line 178 def delete(key) super(convert_key(key)) end |
#dup ⇒ Object
Duplicates the current mash as a new mash.
188 189 190 |
# File 'lib/hashie/mash.rb', line 188 def dup self.class.new(self, default) end |
#extractable_options? ⇒ Boolean
play nice with ActiveSupport Array#extract_options!
283 284 285 |
# File 'lib/hashie/mash.rb', line 283 def true end |
#fetch(key, *args) ⇒ Object
174 175 176 |
# File 'lib/hashie/mash.rb', line 174 def fetch(key, *args) super(convert_key(key), *args) end |
#initializing_reader(key) ⇒ Object
This is the bang method reader, it will return a new Mash if there isn't a value already assigned to the key requested.
157 158 159 160 161 |
# File 'lib/hashie/mash.rb', line 157 def initializing_reader(key) ck = convert_key(key) regular_writer(ck, self.class.new) unless key?(ck) regular_reader(ck) end |
#key?(key) ⇒ Boolean Also known as: has_key?, include?, member?
192 193 194 |
# File 'lib/hashie/mash.rb', line 192 def key?(key) super(convert_key(key)) end |
#prefix_method?(method_name) ⇒ Boolean
260 261 262 263 |
# File 'lib/hashie/mash.rb', line 260 def prefix_method?(method_name) method_name = method_name.to_s method_name.end_with?(*ALLOWED_SUFFIXES) && key?(method_name.chop) end |
#regular_dup ⇒ Object
186 |
# File 'lib/hashie/mash.rb', line 186 alias_method :regular_dup, :dup |
#replace(other_hash) ⇒ Object
244 245 246 247 248 |
# File 'lib/hashie/mash.rb', line 244 def replace(other_hash) (keys - other_hash.keys).each { |key| delete(key) } other_hash.each { |key, value| self[key] = value } self end |
#respond_to_missing?(method_name, *args) ⇒ Boolean
250 251 252 253 254 255 256 257 258 |
# File 'lib/hashie/mash.rb', line 250 def respond_to_missing?(method_name, *args) return true if key?(method_name) suffix = method_suffix(method_name) if suffix true else super end end |
#reverse_merge(other_hash) ⇒ Object
another ActiveSupport method, see issue #270
288 289 290 |
# File 'lib/hashie/mash.rb', line 288 def reverse_merge(other_hash) self.class.new(other_hash).merge(self) end |
#shallow_merge(other_hash) ⇒ Object
Performs a shallow_update on a duplicate of the current mash
231 232 233 |
# File 'lib/hashie/mash.rb', line 231 def shallow_merge(other_hash) dup.shallow_update(other_hash) end |
#shallow_update(other_hash) ⇒ Object
Merges (non-recursively) the hash from the argument, changing the receiving hash
237 238 239 240 241 242 |
# File 'lib/hashie/mash.rb', line 237 def shallow_update(other_hash) other_hash.each_pair do |k, v| regular_writer(convert_key(k), convert_value(v, true)) end self end |
#to_module(mash_method_name = :settings) ⇒ Object
108 109 110 111 112 113 114 115 |
# File 'lib/hashie/mash.rb', line 108 def to_module(mash_method_name = :settings) mash = self Module.new do |m| m.send :define_method, mash_method_name.to_sym do mash end end end |
#underbang_reader(key) ⇒ Object
This is the under bang method reader, it will return a temporary new Mash if there isn't a value already assigned to the key requested.
165 166 167 168 169 170 171 172 |
# File 'lib/hashie/mash.rb', line 165 def underbang_reader(key) ck = convert_key(key) if key?(ck) regular_reader(ck) else self.class.new end end |
#values_at(*keys) ⇒ Object
182 183 184 |
# File 'lib/hashie/mash.rb', line 182 def values_at(*keys) super(*keys.map { |key| convert_key(key) }) end |