lab42_nhash 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +52 -4
- data/demo/100-hierarchies.md +2 -1
- data/demo/120-factories.md +70 -0
- data/demo/applique/file_mockers.rb +26 -0
- data/lib/lab42/nhash/class_methods.rb +39 -1
- data/lib/lab42/nhash/hierarchies.rb +1 -1
- data/lib/lab42/nhash/version.rb +1 -1
- data/lib/lab42/nhash.rb +24 -9
- data/spec/support/file_mocks.rb +15 -0
- data/spec/unit/factories/from_sources_using_hashes_spec.rb +50 -0
- data/spec/unit/factories/from_sources_using_yaml_files_spec.rb +31 -0
- data/spec/unit/factories/inidfferent_access_spec.rb +32 -0
- metadata +14 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dfa964b499cd8f9c9fb458f0082eacf0f990cfac
|
4
|
+
data.tar.gz: f5c06457ecdd6652fd05a33e768791192993a37d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aacab0eb78da5bbeb5b945624e0c2fa058634ba87731dee6803cae4caf27c9e9d21f8910b18a75579528a167d556417b1caeb25bdcea512ca31fd3e614d3f779
|
7
|
+
data.tar.gz: 7aa8904790917d875576b024692427ea49fe3b252096aca527b3c25f101d8afb7a035822262f9a41533cc6d4c402ef68eeefa9afecd893d92f3a86f8c9e8d52d
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -2,10 +2,18 @@
|
|
2
2
|
|
3
3
|
A nested hash view with dotted deep access à la I18n.t of Rails and with optional string interpolation. Typically YML loaded Hashes are used.
|
4
4
|
|
5
|
+
## What is it good for?
|
5
6
|
|
6
|
-
|
7
|
+
I developped `NHash` to scratch an itch that developped when creating presentations of hierarchical data with different aspects. E.g. different languages
|
8
|
+
and different versions.
|
9
|
+
|
10
|
+
For that I wanted to combine the _data_ and define strategies what to do when compound keys were not found. Typically _data_ will be quite a big `Hash`
|
11
|
+
instance coming from _Yaml_ files, a _Json_ webservice, or a document oriented database like _MongoDB_.
|
12
|
+
|
13
|
+
But let us start slowly:
|
14
|
+
|
15
|
+
## Most Basic Example
|
7
16
|
|
8
|
-
Please see the [QED](http://rubyworks.github.io/qed/) demos [here](https://github.com/RobertDober/lab42_nested_hash/blob/master/demo/000-basic-examples.md) for detailed explainations and specifications:
|
9
17
|
|
10
18
|
```ruby
|
11
19
|
h = { "a" => 1,
|
@@ -29,8 +37,48 @@ or _subhashes_:
|
|
29
37
|
```
|
30
38
|
|
31
39
|
|
40
|
+
Please see the [QED](http://rubyworks.github.io/qed/) demos [here](https://github.com/RobertDober/lab42_nested_hash/blob/master/demo) for detailed explainations and specifications of the implemented features:
|
41
|
+
|
42
|
+
|
32
43
|
### Indifferent Access
|
33
44
|
|
34
|
-
|
45
|
+
Symbol and String Keys are treated the same.
|
46
|
+
|
47
|
+
### Affixes
|
48
|
+
|
49
|
+
Prefixes and Suffixes can be predefined and used when a compound key starts and/or ends with a `.`.
|
50
|
+
|
51
|
+
### Lookup Chains
|
52
|
+
|
53
|
+
Taking advantage of the Affixes features an affixed access can look in more than one affix. E.g. to fall back
|
54
|
+
to English as the default translation language.
|
55
|
+
|
56
|
+
### Fallbacks
|
57
|
+
|
58
|
+
A more general concept of what to do if an access fails (raises a `KeyError`).
|
59
|
+
|
60
|
+
### Interpolation
|
61
|
+
|
62
|
+
If values have `ERB` syntax templates as values, the special `get!` access can be used to interpolate them
|
63
|
+
in various contexts, the `NHash` instance's binding being the default.
|
64
|
+
|
65
|
+
### Compound Values
|
66
|
+
|
67
|
+
Subhashes and subarrays maintain important context information, e.g. for _Interpolation_.
|
68
|
+
|
69
|
+
### Hierarchies
|
70
|
+
|
71
|
+
If all else fails...
|
72
|
+
We can check in other `NHash` instances. They are organised as a _Depth First Search Tree_.
|
73
|
+
|
74
|
+
This feature is particularly interesting for complex document composition out of a hierarchical data
|
75
|
+
source tree (e.g. a set of yaml files, different for each new version/variation of the result).
|
76
|
+
|
77
|
+
### Factories
|
78
|
+
|
79
|
+
The `NHash` constructor takes a `Hash` instance (defaulting to `{}` ) as param. This implies that
|
80
|
+
much boiler blate code has to be written in order to bring in other data sources, as e.g. Yaml files.
|
81
|
+
|
82
|
+
The factories help to avoid this.
|
35
83
|
|
36
|
-
|
84
|
+
There are even helpers to create an `NHash` hierarchy from data sources.
|
data/demo/100-hierarchies.md
CHANGED
@@ -20,7 +20,7 @@ Here is an example:
|
|
20
20
|
root.add_hierarchies one, two, three
|
21
21
|
```
|
22
22
|
|
23
|
-
This constructed a tree like the following (denoting `:never_found`
|
23
|
+
This constructed a tree like the following (denoting `:never_found` by a `*`)
|
24
24
|
|
25
25
|
|
26
26
|
```
|
@@ -125,4 +125,5 @@ from its root, e.g. affix chains or fallbacks.
|
|
125
125
|
end
|
126
126
|
```
|
127
127
|
|
128
|
+
|
128
129
|
### Interpolation Context
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# Lab42::NHash QED
|
2
|
+
|
3
|
+
## Factories
|
4
|
+
|
5
|
+
The purpose of factories is to bring in common data sources to create a, potentially hierarchic, `NHash` instance.
|
6
|
+
|
7
|
+
Let us see what the generic factory method `from_sources` does with `Hash` or `NHash` instances first.
|
8
|
+
|
9
|
+
### Creating Hierarchies from Hash alikes
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
nh = NHash.new( 'a' => 1, b: 1 )
|
13
|
+
h = { 'a' => 2, 'b' => 2 }
|
14
|
+
|
15
|
+
hier = NHash.from_sources nh, h
|
16
|
+
|
17
|
+
```
|
18
|
+
|
19
|
+
The hierarchy's root node is on the left, and all hierarchies created by `from_sources` are lists, not trees.
|
20
|
+
|
21
|
+
Demonstration:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
hier.get( 'a' ).assert == 1
|
25
|
+
hier.get( 'b' ).assert == 2
|
26
|
+
```
|
27
|
+
|
28
|
+
|
29
|
+
Maybe you noticed that symbolic keys were not found. That is beacause, this time, we did not specify `with_indifferent_access`
|
30
|
+
|
31
|
+
This can be done too, of course (note again that all keys are transformed to strings as usual:
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
hier = NHash.from_sources_with_indifferent_access nh, h
|
35
|
+
hier.get( :a ).assert == 1
|
36
|
+
hier.get( :b ).assert == 1
|
37
|
+
```
|
38
|
+
|
39
|
+
|
40
|
+
### Creating Hierarchies from YAML Files
|
41
|
+
|
42
|
+
The same works if the data is inside a Yaml file
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
given_a_file named: "one.yml", with: <<-EOF
|
46
|
+
a: 1
|
47
|
+
EOF
|
48
|
+
and_given_a_file named: "two.yml", with: <<-EOF
|
49
|
+
a: 2
|
50
|
+
b: 2
|
51
|
+
EOF
|
52
|
+
```
|
53
|
+
|
54
|
+
Now if we invoke `from_sources` with strings, denoting these files, these strings will be replaced by an `NHash` instance
|
55
|
+
initialized with the `Hash` resulting from YAML loading the content of the file
|
56
|
+
Now if we invoke icodefrom_sourceswith strings, denoting these files, these strings will be replaced by an icodeNHashinstance
|
57
|
+
initialized with the icodeHashresulting from YAML loading the content of the file
|
58
|
+
|
59
|
+
Or in short ;) :
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
yaml_hierarchy = NHash.from_sources 'one.yml', 'two.yml'
|
63
|
+
|
64
|
+
yaml_hierarchy.get( :a ).assert == 1
|
65
|
+
yaml_hierarchy.get( :b ).assert == 2
|
66
|
+
KeyError.assert.raised? do
|
67
|
+
yaml_hierarchy.get :c
|
68
|
+
end
|
69
|
+
```
|
70
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
|
2
|
+
def given_a_file named: required, with: required
|
3
|
+
@files ||= {}
|
4
|
+
stub_file unless @orig_readable
|
5
|
+
@files.update named => with
|
6
|
+
end
|
7
|
+
alias_method :and_given_a_file, :given_a_file
|
8
|
+
|
9
|
+
def erase_all_files
|
10
|
+
@files = {}
|
11
|
+
# Is it necessary to remove methods first?
|
12
|
+
File.define_singleton_method :readable?, &@orig_readable
|
13
|
+
File.define_singleton_method :read, &@orig_read
|
14
|
+
end
|
15
|
+
|
16
|
+
def stub_file
|
17
|
+
@orig_readable = File.method :readable?
|
18
|
+
@orig_read = File.method :read
|
19
|
+
files = @files
|
20
|
+
File.define_singleton_method :readable? do | fn |
|
21
|
+
!!files[ fn ]
|
22
|
+
end
|
23
|
+
File.define_singleton_method :read do | fn |
|
24
|
+
files[ fn ]
|
25
|
+
end
|
26
|
+
end
|
@@ -1,18 +1,56 @@
|
|
1
1
|
require_relative 'enum'
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
|
2
5
|
module Lab42
|
3
6
|
class NHash
|
4
7
|
module ClassMethods
|
5
8
|
|
9
|
+
def from_sources *sources
|
10
|
+
__from_sources__(sources)
|
11
|
+
end
|
12
|
+
|
13
|
+
def from_sources_with_indifferent_access *sources
|
14
|
+
__from_sources__(sources, indifferent_access: true )
|
15
|
+
end
|
16
|
+
|
6
17
|
def from_value value, options={}
|
7
18
|
case value
|
8
19
|
when Hash
|
9
|
-
|
20
|
+
new( value ).import_options options
|
10
21
|
when Enumerable
|
11
22
|
Lab42::NHash::Enum.new value, options
|
12
23
|
else
|
13
24
|
value
|
14
25
|
end
|
15
26
|
end
|
27
|
+
|
28
|
+
private
|
29
|
+
def __from_sources__ sources, indifferent_access: false
|
30
|
+
sources = sources.map{ |source|
|
31
|
+
make_nhash_from source, indifferent_access: indifferent_access
|
32
|
+
}
|
33
|
+
result = sources.shift
|
34
|
+
sources.inject result do | r, s |
|
35
|
+
r.add_hierarchy s
|
36
|
+
s
|
37
|
+
end
|
38
|
+
result
|
39
|
+
end
|
40
|
+
|
41
|
+
def make_nhash_from source, indifferent_access: false
|
42
|
+
case source
|
43
|
+
when Hash
|
44
|
+
new source, indifferent_access: indifferent_access
|
45
|
+
when self
|
46
|
+
indifferent_access ? source.dup.with_indifferent_access : source.dup
|
47
|
+
when String
|
48
|
+
raise ArgumentError, "#{source.inspect} needs to designate a readable yaml file" unless File.readable? source
|
49
|
+
new YAML.load( File.read source ), indifferent_access: indifferent_access
|
50
|
+
else
|
51
|
+
raise ArgumentError, "type of value #{source.inspect} is not implemented (yet)"
|
52
|
+
end
|
53
|
+
end
|
16
54
|
end # module ClassMethods
|
17
55
|
extend ClassMethods
|
18
56
|
end # class NHash
|
data/lib/lab42/nhash/version.rb
CHANGED
data/lib/lab42/nhash.rb
CHANGED
@@ -18,7 +18,7 @@ module Lab42
|
|
18
18
|
forward :pop_binding, to: :@binding_stack, as: :pop
|
19
19
|
forward :push_binding, to: :@binding_stack, as: :push
|
20
20
|
|
21
|
-
attr_reader :hashy, :parent
|
21
|
+
attr_reader :hashy, :hierarchies, :parent
|
22
22
|
|
23
23
|
def export_options
|
24
24
|
{ indifferent_access: @indifferent_access,
|
@@ -41,7 +41,7 @@ module Lab42
|
|
41
41
|
def fallback_or_hierarchy keyexpr, keyexc
|
42
42
|
fallback keyexpr, keyexc
|
43
43
|
rescue KeyError => k
|
44
|
-
|
44
|
+
get_from_hierarchies keyexpr, k
|
45
45
|
end
|
46
46
|
|
47
47
|
def import_options options
|
@@ -57,7 +57,22 @@ module Lab42
|
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
|
+
|
61
|
+
def with_indifferent_access! cache={}
|
62
|
+
__recursive_indifferent_access__ self, {}
|
63
|
+
end
|
60
64
|
private
|
65
|
+
|
66
|
+
def __recursive_indifferent_access__ for_nhash, cache
|
67
|
+
return if cache[ for_nhash.object_id ]
|
68
|
+
|
69
|
+
for_nhash.with_indifferent_access
|
70
|
+
cache.update for_nhash.object_id => true
|
71
|
+
|
72
|
+
for_nhash.hierarchies.each do | hier |
|
73
|
+
__recursive_indifferent_access__ hier, cache
|
74
|
+
end
|
75
|
+
end
|
61
76
|
def complete_keys keys, use_prefix: false, use_suffix: false
|
62
77
|
keys = current_prefix + keys if use_prefix
|
63
78
|
keys += current_suffix if use_suffix
|
@@ -79,18 +94,18 @@ module Lab42
|
|
79
94
|
end
|
80
95
|
end
|
81
96
|
|
82
|
-
def initialize hashy={}
|
97
|
+
def initialize hashy={}, options={}
|
83
98
|
@hashy = hashy
|
84
|
-
init_options
|
99
|
+
init_options options
|
85
100
|
end
|
86
101
|
|
87
|
-
def init_options
|
102
|
+
def init_options options
|
88
103
|
@parent = self
|
89
104
|
|
90
|
-
@indifferent_access = false
|
91
|
-
@suffix_stack = []
|
92
|
-
@prefix_stack = []
|
93
|
-
@binding_stack = []
|
105
|
+
@indifferent_access = options.fetch(:indifferent_access, false)
|
106
|
+
@suffix_stack = options.fetch(:suffix_stack, [])
|
107
|
+
@prefix_stack = options.fetch(:prefix_stack, [])
|
108
|
+
@binding_stack = options.fetch(:binding_stack, [])
|
94
109
|
|
95
110
|
@fallbacks = []
|
96
111
|
@current_fallback_pointer = 0
|
@@ -0,0 +1,15 @@
|
|
1
|
+
|
2
|
+
module FileMocks
|
3
|
+
|
4
|
+
def given_a_file named: required, with: required
|
5
|
+
before do
|
6
|
+
expect( File ).to receive( :readable? ).with( named ).and_return( true ).ordered
|
7
|
+
expect( File ).to receive( :read ).with( named ).and_return( with ).ordered
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
end # module FileMocks
|
12
|
+
|
13
|
+
RSpec.configure do | c |
|
14
|
+
c.extend FileMocks
|
15
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe NHash do
|
4
|
+
context :factories do
|
5
|
+
context :with_hashes do
|
6
|
+
let(:h){{ 'a' => 1, 'c' => 1 }}
|
7
|
+
let(:nh){described_class.new( 'a' => 2, 'b' => 2 )}
|
8
|
+
subject do
|
9
|
+
described_class.from_sources( h, nh )
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'is a NHash instance' do
|
13
|
+
expect( subject ).to be_kind_of described_class
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'finds elements in root' do
|
17
|
+
expect( subject.get( 'a' ) ).to eq 1
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'finds element at 2nd level now' do
|
21
|
+
expect( subject.get( 'b' ) ).to eq 2
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'longer chains' do
|
25
|
+
let(:first){ described_class.new( 'a' => 0) }
|
26
|
+
let(:root){
|
27
|
+
described_class.from_sources first, h, nh
|
28
|
+
}
|
29
|
+
|
30
|
+
it 'finds a at root level' do
|
31
|
+
expect( root.get 'a' ).to eq 0
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'finds c at second level' do
|
35
|
+
expect( root.get 'c' ).to eq 1
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'finds b at last level' do
|
39
|
+
expect( root.get 'b' ).to eq 2
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'does not find d at all' do
|
43
|
+
expect( ->{root.get 'd'} ).to raise_error KeyError
|
44
|
+
end
|
45
|
+
|
46
|
+
end # context 'longer chains'
|
47
|
+
end # context :with_hashes
|
48
|
+
|
49
|
+
end # context :factories
|
50
|
+
end # describe NHash
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe NHash do
|
4
|
+
context :factories do
|
5
|
+
context 'from yaml files' do
|
6
|
+
|
7
|
+
given_a_file named: 'one.yml', with: <<-EOF
|
8
|
+
a: 1
|
9
|
+
EOF
|
10
|
+
given_a_file named: 'two.yml', with: <<-EOF
|
11
|
+
a: 2
|
12
|
+
b: 2
|
13
|
+
EOF
|
14
|
+
subject do
|
15
|
+
described_class.from_sources 'one.yml', 'two.yml'
|
16
|
+
end
|
17
|
+
|
18
|
+
it "finds a's value in the first file" do
|
19
|
+
expect( subject.get :a ).to eq 1
|
20
|
+
end
|
21
|
+
|
22
|
+
it "finds b's value in the first file" do
|
23
|
+
expect( subject.get :b ).to eq 2
|
24
|
+
end
|
25
|
+
|
26
|
+
it "does not find c's value anywhere" do
|
27
|
+
expect( ->{ subject.get :c } ).to raise_error KeyError
|
28
|
+
end
|
29
|
+
end # context 'from yaml files'
|
30
|
+
end # context :factories
|
31
|
+
end # describe NHash
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe NHash do
|
4
|
+
|
5
|
+
context :factories do
|
6
|
+
context 'without indifferent access' do
|
7
|
+
subject do
|
8
|
+
described_class.from_sources( {a: 1}, {'a' => 2, b: 2} )
|
9
|
+
end
|
10
|
+
it 'finds only the stringy "a"' do
|
11
|
+
expect( subject.get( :a ) ).to eq 2
|
12
|
+
end
|
13
|
+
it 'and string "b" is not found at all' do
|
14
|
+
expect( ->{ subject.get :b } ).to raise_error KeyError
|
15
|
+
end
|
16
|
+
end # context :indifferent_access
|
17
|
+
|
18
|
+
context 'however, with indifferent access' do
|
19
|
+
subject do
|
20
|
+
described_class.from_sources_with_indifferent_access( {a: 1}, {'a' => 2, b: 2} )
|
21
|
+
end
|
22
|
+
it 'finds also the symbol :a' do
|
23
|
+
expect( subject.get( :a ) ).to eq 1
|
24
|
+
end
|
25
|
+
it 'as well as the symbol :b' do
|
26
|
+
expect( subject.get( :b ) ).to eq 2
|
27
|
+
end
|
28
|
+
|
29
|
+
end # context 'however, with indifferent access'
|
30
|
+
end # context :factories
|
31
|
+
|
32
|
+
end # describe NHash
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lab42_nhash
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Dober
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-05-
|
11
|
+
date: 2014-05-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: forwarder2
|
@@ -143,6 +143,8 @@ files:
|
|
143
143
|
- demo/080-interpolation.md
|
144
144
|
- demo/090-compound-values.md
|
145
145
|
- demo/100-hierarchies.md
|
146
|
+
- demo/120-factories.md
|
147
|
+
- demo/applique/file_mockers.rb
|
146
148
|
- demo/applique/require_ae.rb
|
147
149
|
- demo/applique/require_nhash.rb
|
148
150
|
- lab42_nhash.gemspec
|
@@ -161,11 +163,15 @@ files:
|
|
161
163
|
- spec/integration/hierarchie_and_lookup_spec.rb
|
162
164
|
- spec/regression_spec.rb
|
163
165
|
- spec/spec_helper.rb
|
166
|
+
- spec/support/file_mocks.rb
|
164
167
|
- spec/unit/afixes/affix_spec.rb
|
165
168
|
- spec/unit/afixes/prefix_spec.rb
|
166
169
|
- spec/unit/afixes/suffix_spec.rb
|
167
170
|
- spec/unit/compound/enum_spec.rb
|
168
171
|
- spec/unit/compound/nhash_spec.rb
|
172
|
+
- spec/unit/factories/from_sources_using_hashes_spec.rb
|
173
|
+
- spec/unit/factories/from_sources_using_yaml_files_spec.rb
|
174
|
+
- spec/unit/factories/inidfferent_access_spec.rb
|
169
175
|
- spec/unit/fallback/fallback_spec.rb
|
170
176
|
- spec/unit/hierarchies/base_spec.rb
|
171
177
|
- spec/unit/hierarchies/tree_form_spec.rb
|
@@ -206,16 +212,22 @@ test_files:
|
|
206
212
|
- demo/080-interpolation.md
|
207
213
|
- demo/090-compound-values.md
|
208
214
|
- demo/100-hierarchies.md
|
215
|
+
- demo/120-factories.md
|
216
|
+
- demo/applique/file_mockers.rb
|
209
217
|
- demo/applique/require_ae.rb
|
210
218
|
- demo/applique/require_nhash.rb
|
211
219
|
- spec/integration/hierarchie_and_lookup_spec.rb
|
212
220
|
- spec/regression_spec.rb
|
213
221
|
- spec/spec_helper.rb
|
222
|
+
- spec/support/file_mocks.rb
|
214
223
|
- spec/unit/afixes/affix_spec.rb
|
215
224
|
- spec/unit/afixes/prefix_spec.rb
|
216
225
|
- spec/unit/afixes/suffix_spec.rb
|
217
226
|
- spec/unit/compound/enum_spec.rb
|
218
227
|
- spec/unit/compound/nhash_spec.rb
|
228
|
+
- spec/unit/factories/from_sources_using_hashes_spec.rb
|
229
|
+
- spec/unit/factories/from_sources_using_yaml_files_spec.rb
|
230
|
+
- spec/unit/factories/inidfferent_access_spec.rb
|
219
231
|
- spec/unit/fallback/fallback_spec.rb
|
220
232
|
- spec/unit/hierarchies/base_spec.rb
|
221
233
|
- spec/unit/hierarchies/tree_form_spec.rb
|