Class: Hashie::Mash
- Extended by:
- Extensions::KeyConflictWarning
- Includes:
- Extensions::RubyVersionCheck
- 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.
- Truthiness (?): Returns true or false depending on the truthiness of the attribute, or false if the key is not 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 # =>
Constant Summary collapse
- ALLOWED_SUFFIXES =
%w[? ! = _].freeze
Class Method Summary collapse
- .load(path, options = {}) ⇒ Object
-
.quiet(*method_keys) ⇒ Object
Creates a new anonymous subclass with key conflict warnings disabled.
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.
-
#invert ⇒ Object
Returns a new instance of the class it was called on, using its keys as values, and its values as keys.
- #key?(key) ⇒ Boolean (also: #has_key?, #include?, #member?)
-
#method_missing(method_name, *args, &blk) ⇒ Object
rubocop:disable Style/MethodMissing.
- #prefix_method?(method_name) ⇒ Boolean
- #regular_dup ⇒ Object
- #regular_key? ⇒ Object
-
#reject(&blk) ⇒ Object
Returns a new instance of the class it was called on, containing elements for which the given block returns false.
- #replace(other_hash) ⇒ Object
- #respond_to_missing?(method_name, *args) ⇒ Boolean
-
#reverse_merge(other_hash) ⇒ Object
another ActiveSupport method, see issue #270.
-
#select(&blk) ⇒ Object
Returns a new instance of the class it was called on, containing elements for which the given block returns true.
-
#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
- #with_accessors! ⇒ Object
Methods included from Extensions::KeyConflictWarning
disable_warnings, disable_warnings?, disabled_warnings, inherited
Methods included from Extensions::RubyVersionCheck
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!
Methods included from Extensions::PrettyInspect
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.
100 101 102 103 |
# File 'lib/hashie/mash.rb', line 100 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
rubocop:disable Style/MethodMissing
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 |
# File 'lib/hashie/mash.rb', line 298 def method_missing(method_name, *args, &blk) # rubocop:disable Style/MethodMissing 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
.load(path, options = {}) ⇒ Object
70 71 72 73 74 75 76 77 78 79 |
# File 'lib/hashie/mash.rb', line 70 def self.load(path, = {}) @_mashes ||= new return @_mashes[path] if @_mashes.key?(path) raise ArgumentError, "The following file doesn't exist: #{path}" unless File.file?(path) = .dup parser = .delete(:parser) { Hashie::Extensions::Parsers::YamlErbParser } @_mashes[path] = new(parser.perform(path, )).freeze end |
.quiet(*method_keys) ⇒ Object
Creates a new anonymous subclass with key conflict warnings disabled. You may pass an array of method symbols to restrict the disabled warnings to. Hashie::Mash.quiet.new(hash) all warnings disabled. Hashie::Mash.quiet(:zip).new(hash) only zip warning is disabled.
111 112 113 114 115 116 |
# File 'lib/hashie/mash.rb', line 111 def self.quiet(*method_keys) @memoized_classes ||= {} @memoized_classes[method_keys] ||= Class.new(self) do disable_warnings(*method_keys) end end |
Instance Method Details
#assign_property(name, value) ⇒ Object
Assigns a value to a key
259 260 261 |
# File 'lib/hashie/mash.rb', line 259 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 a key passed in as a symbol to a string before retrieving.
125 126 127 128 129 130 |
# File 'lib/hashie/mash.rb', line 125 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. Symbol keys will be converted to strings before being set, and Hashes will be converted into Mashes for nesting purposes.
135 136 137 138 |
# File 'lib/hashie/mash.rb', line 135 def custom_writer(key, value, convert = true) #:nodoc: (key) if key.respond_to?(:to_sym) && log_collision?(key.to_sym) regular_writer(convert_key(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.
210 211 212 |
# File 'lib/hashie/mash.rb', line 210 def deep_merge(*other_hashes, &blk) dup.deep_update(*other_hashes, &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.
216 217 218 219 220 221 |
# File 'lib/hashie/mash.rb', line 216 def deep_update(*other_hashes, &blk) other_hashes.each do |other_hash| _deep_update(other_hash, &blk) end self end |
#delete(key) ⇒ Object
166 167 168 |
# File 'lib/hashie/mash.rb', line 166 def delete(key) super(convert_key(key)) end |
#dup ⇒ Object
Duplicates the current mash as a new mash.
195 196 197 |
# File 'lib/hashie/mash.rb', line 195 def dup self.class.new(self, default, &default_proc) end |
#extractable_options? ⇒ Boolean
play nice with ActiveSupport Array#extract_options!
316 317 318 |
# File 'lib/hashie/mash.rb', line 316 def true end |
#fetch(key, *args) ⇒ Object
162 163 164 |
# File 'lib/hashie/mash.rb', line 162 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.
145 146 147 148 149 |
# File 'lib/hashie/mash.rb', line 145 def initializing_reader(key) ck = convert_key(key) regular_writer(ck, self.class.new) unless key?(ck) regular_reader(ck) end |
#invert ⇒ Object
Returns a new instance of the class it was called on, using its keys as values, and its values as keys. The new values and keys will always be strings.
177 178 179 |
# File 'lib/hashie/mash.rb', line 177 def invert self.class.new(super) end |
#key?(key) ⇒ Boolean Also known as: has_key?, include?, member?
200 201 202 |
# File 'lib/hashie/mash.rb', line 200 def key?(key) super(convert_key(key)) end |
#prefix_method?(method_name) ⇒ Boolean
293 294 295 296 |
# File 'lib/hashie/mash.rb', line 293 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
193 |
# File 'lib/hashie/mash.rb', line 193 alias regular_dup dup |
#regular_key? ⇒ Object
199 |
# File 'lib/hashie/mash.rb', line 199 alias regular_key? key? |
#reject(&blk) ⇒ Object
Returns a new instance of the class it was called on, containing elements for which the given block returns false.
183 184 185 |
# File 'lib/hashie/mash.rb', line 183 def reject(&blk) self.class.new(super(&blk)) end |
#replace(other_hash) ⇒ Object
277 278 279 280 281 |
# File 'lib/hashie/mash.rb', line 277 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
283 284 285 286 287 288 289 290 291 |
# File 'lib/hashie/mash.rb', line 283 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
321 322 323 |
# File 'lib/hashie/mash.rb', line 321 def reverse_merge(other_hash) self.class.new(other_hash).merge(self) end |
#select(&blk) ⇒ Object
Returns a new instance of the class it was called on, containing elements for which the given block returns true.
189 190 191 |
# File 'lib/hashie/mash.rb', line 189 def select(&blk) self.class.new(super(&blk)) end |
#shallow_merge(other_hash) ⇒ Object
Performs a shallow_update on a duplicate of the current mash
264 265 266 |
# File 'lib/hashie/mash.rb', line 264 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
270 271 272 273 274 275 |
# File 'lib/hashie/mash.rb', line 270 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
81 82 83 84 85 86 87 88 |
# File 'lib/hashie/mash.rb', line 81 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.
153 154 155 156 157 158 159 160 |
# File 'lib/hashie/mash.rb', line 153 def underbang_reader(key) ck = convert_key(key) if key?(ck) regular_reader(ck) else self.class.new end end |
#values_at(*keys) ⇒ Object
170 171 172 |
# File 'lib/hashie/mash.rb', line 170 def values_at(*keys) super(*keys.map { |key| convert_key(key) }) end |
#with_accessors! ⇒ Object
90 91 92 |
# File 'lib/hashie/mash.rb', line 90 def with_accessors! extend Hashie::Extensions::Mash::DefineAccessors end |