Lab42::DiggyMethods
Access (nested) hash values by means of method chaining
Usage
gem install lab42_diggy_methods
With bundler
gem 'lab42_diggy_methods'
In your code
require 'lab42/diggy_methods'
So what does it do?
Well let us speculate about it to find out:
Context: Diggy function
An extension to the Kernel as an alias for Lab42::DiggyMethods.new
Given
let(:data) { {a: 1, b: {c: 2, d: {e: 3}}} }
let(:diggy) { Diggy(**data) }
Then we can access its fields as follows
expect(diggy.a).to eq(1)
expect(diggy.b.d.__data__).to eq(e: 3)
expect(diggy.b.d.e).to eq(3)
And we can use a shortcut for key.__data__ by using key!
expect(diggy.b.d!).to eq(e: 3)
And that works for leave nodes too of course
expect(diggy.a!).to eq(1)
And in case of missing keys
expect{ diggy.b.d.f }.to raise_error(KeyError, "key not found: b.d.f")
And this works for arrays too:
with_array = Diggy(a: [b: {}])
expect { with_array.a.first.b.c }.to raise_error(KeyError, "key not found: a.b.c")
If we access unknown keys we get the usual KeyError error, however we must not pass, nonhashable data
But if we pass an array
expect{ Diggy([:a]) }.to raise_error(ArgumentError)
Context: Using in ERB with __binding__
In order to take advantage of this syntax we want to pass the binding of a Diggy object to ERB
Given an ERB template
require 'erb'
let(:template_text) { "<%= data.person.name %>" }
And a Lab42::DiggyMethod instance
let(:data) { Diggy(data: {person: {name: "YHS"}}) }
Then we can pass the binding to the template
expect(ERB.new(template_text).result(data.__binding__)).to eq("YHS")
Context: Merging bindings
In some cases Diggy will not be the only useful binding in an ERB Template
we can work around this as follows
Given a diggy and a module
let(:diggy) { Diggy(a: 1) }
let :mod do
Module.new do
def b; 42 end
end
end
And we extend the diggy with the module
before { diggy.extend(mod) }
Then the module's methods become accessible in the binding
expect(diggy.__binding__.eval("b")).to eq(42)
Context: Iteration
If an element in a diggy object is an array we descend
Given yet another diggy™
let(:diggy) { Diggy(a: [b: 1, c: 2]) }
Then we get an array
expect(diggy.a).to be_an(Array)
And it contains diggy instances
expect(diggy.a.first.b).to eq(1)
LICENSE
Copyright 2022 Robert Dober [email protected]
Apache-2.0 c.f LICENSE