Skip to content

Instantly share code, notes, and snippets.

@wheeyls
Created October 11, 2012 05:26
Show Gist options
  • Save wheeyls/3870384 to your computer and use it in GitHub Desktop.
Save wheeyls/3870384 to your computer and use it in GitHub Desktop.
Simple DSL to safely traverse a hash with unknown values, performing specific actions with selected values along the way.
class Dsl
attr_accessor :hash
def initialize(hash, &block)
@hash = hash
instance_eval(&block)
end
def method_missing(key_name, *args)
key_name = prepare_key(key_name)
if is_valid_key(key_name)
@hash[key_name]
end
end
def is_valid_key(key_name)
if key_name.class == Fixnum
@hash.class == Array && @hash.length >= key_name
else
@hash.keys.include?(key_name)
end
end
def prepare_key(key_name)
for_arrays = key_name.to_s.match(/^_([0-9]+)$/)
key_name = for_arrays[1].to_i if for_arrays && for_arrays[1]
key_name
end
def traverse(node_name, &block)
Dsl.new(@hash[node_name], &block)
end
end
require './lib.rb'
describe Dsl do
before :each do
@hash = {
item: 1,
thing: 2,
one_level: {
item: 3
},
deeper: {
and_deeper: {
stuff: 4,
arr: [ 5, 6, 7 ]
}
}
}
end
it 'takes a hash' do
success = false
Dsl.new(@hash) do
success = true
end
success.should == true
end
it 'can call values at the current level' do
result = nil
Dsl.new(@hash) do
result = item
end
result.should == 1
end
it 'throws no errors for failures' do
result = nil
Dsl.new(@hash) do
result = not_here
end
result.should == nil
end
it 'can traverse child nodes' do
root_res = nil
child_res = nil
Dsl.new(@hash) do
root_res = item
traverse :one_level do
child_res = item
end
end
root_res.should == 1
child_res.should == 3
end
describe 'arrays' do
it 'can directly hit an array' do
values = []
Dsl.new([1,2,3]) do
values << _0
values << _1
values << _2
end
values.should == [1,2,3]
end
it 'can loop over an array' do
values = []
Dsl.new(arr: [1,2,3]) do
arr.each do |i|
values << i
end
end
values.should == [1,2,3]
end
end
it 'can hit every node' do
values = []
Dsl.new(@hash) do
values << item
values << thing
traverse :one_level do
values << item
end
traverse :deeper do
traverse :and_deeper do
values << stuff
traverse :arr do
values << _0
values << _1
values << _2
end
end
end
end
values.should == [1,2,3,4,5,6,7]
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment