Class: Hashie::Blash
- Inherits:
-
Hash
- Object
- Hash
- Hashie::Blash
- Includes:
- PrettyInspect
- Defined in:
- lib/hashie/blash.rb
Overview
Blash allows you to create Mash-like objects with a block syntax for creating nested hashes. This is useful for building deeply nested configuration hashes, similar in style to many dsl based configuration files.
A Blash 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.
-
With Block (
{...}
): Sets key to and yields a new blash -
Assignment (
=
): Sets the attribute of the given method name. -
Existence (
?
): Returns true or false depending on whether that key has been set.
Basic Example
blash = Blash.new
blash.name? # => false
blash.name = "Bob"
blash.name # => "Bob"
blash.name? # => true
Hash Conversion Example
hash = {:a => {:b => 23, :d => {:e => "abc"}}, :f => [{:g => 44, :h => 29}, 12]}
blash = Blash.new(hash)
blash.a.b # => 23
blash.a.d.e # => "abc"
blash.f.first.g # => 44
blash.f.last # => 12
Block Example
blash = Blash.new
blash. do |a|
a.name = "Michael Bleigh"
end
blash. # => <Blash name="Michael Bleigh">
blash..name # => "Michael Bleigh"
Instance Method Summary collapse
-
#custom_reader(key) {|value| ... } ⇒ Object
(also: #[])
Retrieves an attribute set in the Blash.
-
#custom_writer(key, value) ⇒ Object
(also: #[]=)
Sets an attribute in the Blash.
-
#deep_merge(other_hash, &blk) ⇒ Object
(also: #merge)
Performs a deep_update on a duplicate of the current blash.
-
#deep_update(other_hash, &blk) ⇒ Object
(also: #deep_merge!, #update)
Recursively merges this blash with the passed in hash, merging each hash in the hierarchy.
- #delete(key) ⇒ Object
-
#dup ⇒ Object
Duplicates the current blash as a new blash.
- #fetch(key, *args) ⇒ Object
-
#id ⇒ Object
:nodoc:.
-
#initialize(source_hash = nil, default = nil, &blk) ⇒ Blash
constructor
If you pass in an existing hash, it will convert it to a Blash 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 Blash 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
- #regular_dup ⇒ Object
- #replace(other_hash) ⇒ Object
-
#respond_to?(method_name, include_private = false) ⇒ Boolean
Will return true if the Blash has had a key set in addition to normal respond_to? functionality.
-
#shallow_merge(other_hash) ⇒ Object
Performs a shallow_update on a duplicate of the current blash.
-
#shallow_update(other_hash) ⇒ Object
Merges (non-recursively) the hash from the argument, changing the receiving hash.
-
#type ⇒ Object
:nodoc:.
Constructor Details
#initialize(source_hash = nil, default = nil, &blk) ⇒ Blash
If you pass in an existing hash, it will convert it to a Blash including recursively descending into arrays and hashes, converting them as well.
51 52 53 54 |
# File 'lib/hashie/blash.rb', line 51 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
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/hashie/blash.rb', line 169 def method_missing(method_name, *args, &blk) match = method_name.to_s.match(/(.*?)([?=]?)$/) if block_given? super unless match[2].empty? raise ArgumentError, "wrong number of arguments (#{args.size} for 0)" if args.size > 1 if key?(method_name) && ! self.[](method_name).is_a?(Blash) raise TypeError, "key '#{method_name}' already contains a #{self.[](method_name).class}" end val = self.[](method_name) || initializing_reader(method_name) yield val return val else if key?(method_name) raise ArgumentError, "wrong number of arguments (#{args.size} for 0)" unless args.empty? return self.[](method_name, &blk) end case match[2] when "=" raise ArgumentError, "wrong number of arguments (#{args.size} for 1)" unless args.size == 1 self[match[1]] = args.first when "?" raise ArgumentError, "wrong number of arguments (#{args.size} for 0)" unless args.empty? !!self[match[1]] when "" raise ArgumentError, "wrong number of arguments (#{args.size} for 0)" unless args.empty? default(method_name) else super end end end |
Instance Method Details
#custom_reader(key) {|value| ... } ⇒ Object Also known as: []
Retrieves an attribute set in the Blash. Will convert any key passed in to a string before retrieving.
71 72 73 74 75 |
# File 'lib/hashie/blash.rb', line 71 def custom_reader(key) value = regular_reader(convert_key(key)) yield value if block_given? value end |
#custom_writer(key, value) ⇒ Object Also known as: []=
Sets an attribute in the Blash. Key will be converted to a string before it is set, and Hashes will be converted into Blashes for nesting purposes.
80 81 82 |
# File 'lib/hashie/blash.rb', line 80 def custom_writer(key,value) #:nodoc: regular_writer(convert_key(key), convert_value(value)) end |
#deep_merge(other_hash, &blk) ⇒ Object Also known as: merge
Performs a deep_update on a duplicate of the current blash.
118 119 120 |
# File 'lib/hashie/blash.rb', line 118 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 blash with the passed in hash, merging each hash in the hierarchy.
125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/hashie/blash.rb', line 125 def deep_update(other_hash, &blk) other_hash.each_pair do |k,v| key = convert_key(k) if regular_reader(key).is_a?(Blash) and v.is_a?(::Hash) custom_reader(key).deep_update(v, &blk) else value = convert_value(v, true) value = blk.call(key, self[k], value) if blk custom_writer(key, value) end end self end |
#delete(key) ⇒ Object
99 100 101 |
# File 'lib/hashie/blash.rb', line 99 def delete(key) super(convert_key(key)) end |
#dup ⇒ Object
Duplicates the current blash as a new blash.
105 106 107 |
# File 'lib/hashie/blash.rb', line 105 def dup self.class.new(self, self.default) end |
#fetch(key, *args) ⇒ Object
95 96 97 |
# File 'lib/hashie/blash.rb', line 95 def fetch(key, *args) super(convert_key(key), *args) end |
#id ⇒ Object
:nodoc:
58 59 60 |
# File 'lib/hashie/blash.rb', line 58 def id #:nodoc: self["id"] end |
#initializing_reader(key) ⇒ Object
This is the bang method reader, it will return a new Blash if there isn’t a value already assigned to the key requested.
89 90 91 92 93 |
# File 'lib/hashie/blash.rb', line 89 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?
109 110 111 |
# File 'lib/hashie/blash.rb', line 109 def key?(key) super(convert_key(key)) end |
#regular_dup ⇒ Object
103 |
# File 'lib/hashie/blash.rb', line 103 alias_method :regular_dup, :dup |
#replace(other_hash) ⇒ Object
156 157 158 159 160 |
# File 'lib/hashie/blash.rb', line 156 def replace(other_hash) (keys - other_hash.keys).each { |key| delete(key) } other_hash.each { |key, value| self[key] = value } self end |
#respond_to?(method_name, include_private = false) ⇒ Boolean
Will return true if the Blash has had a key set in addition to normal respond_to? functionality.
164 165 166 167 |
# File 'lib/hashie/blash.rb', line 164 def respond_to?(method_name, include_private=false) return true if key?(method_name) || method_name.to_s.slice(/[=?]\Z/) super end |
#shallow_merge(other_hash) ⇒ Object
Performs a shallow_update on a duplicate of the current blash
143 144 145 |
# File 'lib/hashie/blash.rb', line 143 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
149 150 151 152 153 154 |
# File 'lib/hashie/blash.rb', line 149 def shallow_update(other_hash) other_hash.each_pair do |k,v| regular_writer(convert_key(k), convert_value(v, true)) end self end |
#type ⇒ Object
:nodoc:
62 63 64 |
# File 'lib/hashie/blash.rb', line 62 def type #:nodoc: self["type"] end |