Class: Philiprehberger::DotAccess::Wrapper
- Inherits:
-
Object
- Object
- Philiprehberger::DotAccess::Wrapper
- Includes:
- Enumerable
- Defined in:
- lib/philiprehberger/dot_access.rb
Overview
Dot-notation wrapper for a hash
Instance Method Summary collapse
- #==(other) ⇒ Boolean
-
#compact ⇒ Wrapper
Return a new Wrapper with all nil values removed at every depth.
-
#delete(path) ⇒ Wrapper
Remove a key at a dot-path, returning a new Wrapper.
-
#dig(key) ⇒ Object
private
Dig into nested keys.
-
#each {|Symbol, Object| ... } ⇒ Enumerator
(also: #each_pair)
Iterate over top-level key-value pairs.
-
#empty? ⇒ Boolean
Check if the wrapped hash has no keys.
-
#exists?(path) ⇒ Boolean
Check if a dot-separated path exists in the wrapped hash.
-
#fetch!(path) ⇒ Object
Fetch a value at a dot-path, raising if missing.
-
#flatten ⇒ Hash
Flatten nested structure into a hash with dot-path keys.
-
#get(path, default: nil) ⇒ Object
Access a value by dot-path string.
-
#initialize(hash) ⇒ Wrapper
constructor
A new instance of Wrapper.
- #inspect ⇒ String
-
#key?(key) ⇒ Boolean
private
Check if a key exists in the underlying data.
-
#keys(depth: nil) ⇒ Array<String>
Return all dot-path keys as strings.
-
#merge(other) ⇒ Wrapper
Deep merge with another Wrapper or Hash.
-
#set(path, value) ⇒ Wrapper
Set a value at a dot-path, returning a new Wrapper.
-
#size ⇒ Integer
(also: #count)
Return the number of top-level keys.
-
#slice(*paths) ⇒ Wrapper
Return a new Wrapper containing only the specified dot-paths.
-
#to_h ⇒ Hash
Return the underlying hash.
-
#to_json(*args) ⇒ String
Serialize the wrapped hash to a JSON string.
-
#to_yaml(*args) ⇒ String
Serialize the wrapped hash to a YAML string.
-
#values_at(*paths) ⇒ Array<Object>
Return values at the given dot-paths as an array.
Constructor Details
#initialize(hash) ⇒ Wrapper
Returns a new instance of Wrapper.
100 101 102 103 104 105 |
# File 'lib/philiprehberger/dot_access.rb', line 100 def initialize(hash) @data = hash.each_with_object({}) do |(key, value), memo| memo[key.is_a?(String) ? key.to_sym : key] = value end freeze end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name, *args) ⇒ Object (private)
320 321 322 323 324 325 326 327 328 |
# File 'lib/philiprehberger/dot_access.rb', line 320 def method_missing(name, *args) if @data.key?(name) wrap_value(@data[name]) elsif name.to_s.end_with?('=') || !args.empty? super else NullAccess.new end end |
Instance Method Details
#==(other) ⇒ Boolean
312 313 314 315 316 |
# File 'lib/philiprehberger/dot_access.rb', line 312 def ==(other) return to_h == other.to_h if other.is_a?(Wrapper) false end |
#compact ⇒ Wrapper
Return a new Wrapper with all nil values removed at every depth
220 221 222 |
# File 'lib/philiprehberger/dot_access.rb', line 220 def compact Philiprehberger::DotAccess.wrap(deep_compact(to_h)) end |
#delete(path) ⇒ Wrapper
Remove a key at a dot-path, returning a new Wrapper
204 205 206 207 208 |
# File 'lib/philiprehberger/dot_access.rb', line 204 def delete(path) keys = path.to_s.split('.') new_data = deep_delete(to_h, keys) Wrapper.new(new_data) end |
#dig(key) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Dig into nested keys
301 302 303 304 |
# File 'lib/philiprehberger/dot_access.rb', line 301 def dig(key) value = @data[key] wrap_value(value) end |
#each {|Symbol, Object| ... } ⇒ Enumerator Also known as: each_pair
Iterate over top-level key-value pairs
238 239 240 241 242 243 244 |
# File 'lib/philiprehberger/dot_access.rb', line 238 def each(&) return enum_for(:each) unless block_given? @data.each do |key, value| yield key, wrap_value(value) end end |
#empty? ⇒ Boolean
Check if the wrapped hash has no keys
251 252 253 |
# File 'lib/philiprehberger/dot_access.rb', line 251 def empty? @data.empty? end |
#exists?(path) ⇒ Boolean
Check if a dot-separated path exists in the wrapped hash
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/philiprehberger/dot_access.rb', line 140 def exists?(path) keys = path.to_s.split('.') current = @data keys.each do |key| case current when Hash return false unless current.key?(key.to_sym) current = current[key.to_sym] when Wrapper return false unless current.key?(key.to_sym) current = current[key.to_sym] else return false end end true end |
#fetch!(path) ⇒ Object
Fetch a value at a dot-path, raising if missing
173 174 175 176 177 |
# File 'lib/philiprehberger/dot_access.rb', line 173 def fetch!(path) raise KeyError, "path not found: #{path.inspect}" unless exists?(path) get(path) end |
#flatten ⇒ Hash
Flatten nested structure into a hash with dot-path keys
213 214 215 |
# File 'lib/philiprehberger/dot_access.rb', line 213 def flatten flatten_hash(@data, '') end |
#get(path, default: nil) ⇒ Object
Access a value by dot-path string
112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/philiprehberger/dot_access.rb', line 112 def get(path, default: nil) keys = path.to_s.split('.') result = keys.reduce(@data) do |current, key| case current when Hash then current[key.to_sym] when Wrapper then current[key.to_sym] else return default end end result.nil? ? default : result end |
#inspect ⇒ String
307 308 309 |
# File 'lib/philiprehberger/dot_access.rb', line 307 def inspect "#<DotAccess::Wrapper #{to_h.inspect}>" end |
#key?(key) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Check if a key exists in the underlying data
283 284 285 |
# File 'lib/philiprehberger/dot_access.rb', line 283 def key?(key) @data.key?(key) end |
#keys(depth: nil) ⇒ Array<String>
Return all dot-path keys as strings
164 165 166 |
# File 'lib/philiprehberger/dot_access.rb', line 164 def keys(depth: nil) collect_keys(@data, '', depth, 1) end |
#merge(other) ⇒ Wrapper
Deep merge with another Wrapper or Hash
228 229 230 231 232 |
# File 'lib/philiprehberger/dot_access.rb', line 228 def merge(other) other_hash = other.is_a?(Wrapper) ? other.to_h : symbolize_keys(other) merged = deep_merge(to_h, other_hash) Wrapper.new(merged) end |
#set(path, value) ⇒ Wrapper
Set a value at a dot-path, returning a new Wrapper
130 131 132 133 134 |
# File 'lib/philiprehberger/dot_access.rb', line 130 def set(path, value) keys = path.to_s.split('.') new_data = deep_set(to_h, keys, value) Wrapper.new(new_data) end |
#size ⇒ Integer Also known as: count
Return the number of top-level keys
258 259 260 |
# File 'lib/philiprehberger/dot_access.rb', line 258 def size @data.size end |
#slice(*paths) ⇒ Wrapper
Return a new Wrapper containing only the specified dot-paths
183 184 185 186 187 188 189 190 |
# File 'lib/philiprehberger/dot_access.rb', line 183 def slice(*paths) new_data = paths.reduce({}) do |acc, path| next acc unless exists?(path) deep_set(acc, path.to_s.split('.'), get(path)) end Wrapper.new(new_data) end |
#to_h ⇒ Hash
Return the underlying hash
290 291 292 293 294 |
# File 'lib/philiprehberger/dot_access.rb', line 290 def to_h @data.each_with_object({}) do |(key, value), memo| memo[key] = value.is_a?(Wrapper) ? value.to_h : value end end |
#to_json(*args) ⇒ String
Serialize the wrapped hash to a JSON string
267 268 269 |
# File 'lib/philiprehberger/dot_access.rb', line 267 def to_json(*args) to_h.to_json(*args) end |
#to_yaml(*args) ⇒ String
Serialize the wrapped hash to a YAML string
274 275 276 |
# File 'lib/philiprehberger/dot_access.rb', line 274 def to_yaml(*args) to_h.to_yaml(*args) end |
#values_at(*paths) ⇒ Array<Object>
Return values at the given dot-paths as an array
196 197 198 |
# File 'lib/philiprehberger/dot_access.rb', line 196 def values_at(*paths) paths.map { |path| get(path) } end |