bathysphere 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: cf41646c705b635a1110c58b0dee1f78b1aefc0a
4
+ data.tar.gz: 5ac3f636dc2358b1e0c1d08b25d00561a1eabfa0
5
+ SHA512:
6
+ metadata.gz: 3aeb845bec1800bbe7d32fb10a72b7ccf12f3f4be264fab0ede971b3c01dd0de7e50f34e12b0937706c7a97d23cb8044e2d863e192b96c4301961e5ed678fdb1
7
+ data.tar.gz: 9024f28ac5f208c7dd244f1ed4a9734cbbae521c388cbf83174538f1958de2749cfcc5e1d46cd6f12939ca95d6db893a3857fa9775b9e5d4c031dcdaac36fbe7
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in bathysphere.gemspec
4
+ gemspec
5
+
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2016, 2017 Redbubble
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included
12
+ in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,254 @@
1
+ Bathysphere
2
+ ===========
3
+
4
+ [![Gem Version](https://badge.fury.io/rb/bathysphere.svg)](http://badge.fury.io/rb/bathysphere)
5
+ [![Build Status](https://travis-ci.org/redbubble/bathysphere.svg?branch=master)](https://travis-ci.org/redbubble/bathysphere)
6
+ [![Code Climate](https://codeclimate.com/github/redbubble/bathysphere.svg)](https://codeclimate.com/github/redbubble/bathysphere)
7
+ [![Dependency Status](https://gemnasium.com/redbubble/bathysphere.svg)](https://gemnasium.com/redbubble/bathysphere)
8
+ [![Inline docs](http://inch-ci.org/github/redbubble/bathysphere.svg?branch=master)](http://inch-ci.org/github/redbubble/bathysphere)
9
+
10
+ Fetch arbitrarily deep properties from YAML files without loosing your breath.
11
+
12
+ Bathysphere takes benefit of a self-describing YAML-based data format to
13
+ normalize options fetching, so the same option can be stored at different
14
+ depths in distinct configuration files.
15
+
16
+ > **NOTICE**: Contributions to make Bathysphere amazing are highly encouraged! And at any moment, [feedback][issues] is welcome! : )
17
+
18
+ [intent]: doc/README.md
19
+ [issues]: https://github.com/redbubble/bathysphere/issues
20
+
21
+ Installation
22
+ ------------
23
+
24
+ Add the gem to your `Gemfile`:
25
+
26
+ ```ruby
27
+ # Gemfile
28
+
29
+ gem 'bathysphere', '~> 1.0' # see semver.org
30
+ ```
31
+
32
+ [gemfury]: https://gemfury.com
33
+
34
+ Usage
35
+ -----
36
+
37
+ ### Basics
38
+
39
+ Define your configuration files. The `key` is the self-documenting part of the configuration file, and it defines how deep the `values` must be fetched:
40
+
41
+
42
+ ```yaml
43
+ # config/products/fruit.yml
44
+
45
+ ---
46
+ display_name:
47
+ key: 'size,color'
48
+ values:
49
+ small:
50
+ green: 'Grape'
51
+ orange: 'Kumquat'
52
+ purple: 'Blueberry'
53
+ medium:
54
+ green: 'Pear'
55
+ orange: 'Orange'
56
+ purple: 'Plum'
57
+ large:
58
+ green: 'Watermelon'
59
+ orange: 'Melon'
60
+ purple: 'Eggplant'
61
+ ```
62
+
63
+ ```yaml
64
+ # config/product/vehicle.yml
65
+
66
+ ---
67
+ display_name:
68
+ key: 'size'
69
+ values:
70
+ large: 'Train'
71
+ medium: 'Bus'
72
+ small: 'Bike'
73
+ ```
74
+
75
+ Create a `Bathysphere::Parser` for each configuration file (note that you don't need to know how deep the values are defined):
76
+
77
+
78
+ ```ruby
79
+ # app/models/product.rb
80
+
81
+ require 'bathysphere'
82
+
83
+ class Product
84
+
85
+ def self.configuration
86
+ @configuration ||= Bathysphere::Parser.new("config/products/#{name}.yml")
87
+ end
88
+
89
+ def configuration
90
+ self.class.configuration
91
+ end
92
+
93
+ def display_name
94
+ raise NotImplementedError
95
+ end
96
+ end
97
+ ```
98
+
99
+ The same `Bathysphere::Parser#fetch` method can be used to fetch all the `display_name` values, using exactly the required arguments:
100
+
101
+ ```ruby
102
+ # app/models/fruit.rb
103
+
104
+ class Fruit < Product
105
+
106
+ def initialize(size, color)
107
+ @size = size
108
+ @color = color
109
+ end
110
+
111
+ def display_name
112
+ configuration.fetch(:display_name, @size, @color)
113
+ end
114
+ end
115
+ ```
116
+
117
+ ```ruby
118
+ # app/models/vehicle.rb
119
+
120
+ class Vehicle < Product
121
+
122
+ def initialize(size)
123
+ @size = size
124
+ end
125
+
126
+ def display_name
127
+ configuration.fetch(:display_name, @size)
128
+ end
129
+ end
130
+ ```
131
+
132
+ A nice and easy way to implement duck types for different kinds of products!
133
+
134
+
135
+ ```ruby
136
+ # anywhere
137
+
138
+ products = [
139
+ Fruit.new(:large, :purple),
140
+ Vehicle.new(:small),
141
+ Fruit.new(:small, :green),
142
+ Fruit.new(:small, :orange),
143
+ Vehicle.new(:large),
144
+ ]
145
+
146
+ products.map(&display_name)
147
+ # => ["Eggplant", "Bike", "Grape", "Kumquat", "Train"]
148
+ ```
149
+
150
+ ### Further automation
151
+
152
+ Sometimes, defining the reader methods for the configurable properites is not practical. (Maybe your products are generated dynamically, or you want to keep the duck type obvious by keeping these readers in the `Product` class.)
153
+
154
+ Optionally, the additional arguments to the `Parser#fetch` method can be retrieved automatically from any object provided to the `Parser#using` method:
155
+
156
+ ```ruby
157
+ # app/models/product.rb
158
+
159
+ require 'bathysphere'
160
+
161
+ class Product
162
+
163
+ def self.configuration
164
+ @configuration ||= Bathysphere::Parser.new("config/products/#{name}.yml")
165
+ end
166
+
167
+ def configuration
168
+ self.class.configuration
169
+ end
170
+
171
+ def display_name
172
+ # Note that only :display_name was provided as an argument to Parser#fetch,
173
+ # the additional arguments will be retrieved by calling the corresponding
174
+ # reader methods on whatever object is provided to Parser#using, which in
175
+ # this case is the product instance.
176
+ configuration.using(self).fetch(:display_name)
177
+ end
178
+ end
179
+ ```
180
+
181
+ ```ruby
182
+ # app/models/fruit.rb
183
+
184
+ class Fruit < Product
185
+
186
+ # These readers will be automatically called by Bathysphere::Parser#fetch
187
+ # to retrieve the Fruit#display_name - note that the parser is using(self)
188
+ attr_reader :color, :size
189
+
190
+ def initialize(size, color)
191
+ @size = size
192
+ @color = color
193
+ end
194
+ end
195
+ ```
196
+
197
+ ```ruby
198
+ # app/models/vehicle.rb
199
+
200
+ class Vehicle < Product
201
+
202
+ # This reader will be automatically called by Bathysphere::Parser#fetch
203
+ # to retrieve the Vehicle#display_name - note that the parser is using(self)
204
+ attr_reader :size
205
+
206
+ def initialize(size)
207
+ @size = size
208
+ end
209
+ end
210
+ ```
211
+
212
+ Contributions
213
+ -------------
214
+
215
+ Contributions are welcome! Please feel free to open issues or pull requests to get help or discuss ideas or implementations. Note that opening pull requests with work in progress is not only welcome, but encouraged! Talk early, talk often, and we will all learn in the way :)
216
+
217
+ Finally, please note that this project is released with a [Contributor Code of Conduct][coc]. By participating in this project you agree to abide by its terms.
218
+
219
+ [coc]: ./CODE_OF_CONDUCT.md
220
+
221
+ Credits
222
+ -------
223
+
224
+ [![](doc/redbubble.png)][redbubble]
225
+
226
+ Bathysphere is maintained and funded by [Redbubble][redbubble].
227
+
228
+ [redbubble]: https://www.redbubble.com
229
+
230
+ License
231
+ -------
232
+
233
+ Bathysphere
234
+ Copyright (C) 2016, 2017 Redbubble
235
+
236
+ Permission is hereby granted, free of charge, to any person obtaining
237
+ a copy of this software and associated documentation files (the
238
+ "Software"), to deal in the Software without restriction, including
239
+ without limitation the rights to use, copy, modify, merge, publish,
240
+ distribute, sublicense, and/or sell copies of the Software, and to
241
+ permit persons to whom the Software is furnished to do so, subject to
242
+ the following conditions:
243
+
244
+ The above copyright notice and this permission notice shall be included
245
+ in all copies or substantial portions of the Software.
246
+
247
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
248
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
249
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
250
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
251
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
252
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
253
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
254
+
@@ -0,0 +1,12 @@
1
+ require "bundler/gem_tasks"
2
+ require 'cucumber/rake/task'
3
+ require "rspec/core/rake_task"
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ Cucumber::Rake::Task.new(:features) do |t|
8
+ t.cucumber_opts = 'features --format pretty'
9
+ end
10
+
11
+ task default: [:features, :spec]
12
+
@@ -0,0 +1,21 @@
1
+ Intended API
2
+ ============
3
+
4
+ This document is intended to allow discussing the Bathysphere API before it is implemented.
5
+
6
+ Its contents will be moved to the gem [`README`][readme] when the corresponding features are implemented.
7
+
8
+ [readme]: ../README.md
9
+
10
+ Installation
11
+ ------------
12
+
13
+ Add the gem to your `Gemfile`:
14
+
15
+ ```ruby
16
+ # Gemfile
17
+
18
+ gem 'bathysphere', '~> 1,0' # see semver.org
19
+ ```
20
+
21
+ _There are no other upcoming changes at the moment._
Binary file
@@ -0,0 +1,4 @@
1
+ require "bathysphere/parser"
2
+ require "bathysphere/version"
3
+
4
+ module Bathysphere; end
@@ -0,0 +1,65 @@
1
+ require 'yaml'
2
+
3
+ module Bathysphere
4
+ class Parser
5
+
6
+ attr_reader :file, :refinements_store
7
+ private :file, :refinements_store
8
+
9
+ def initialize(file_path)
10
+ @file = file_path.downcase
11
+ @data = YAML.load_file(file)
12
+ end
13
+
14
+ # Set a refinements store
15
+ #
16
+ # When a refinements store is available, the #fetch
17
+ # method will attempt to retrieve the refinements by
18
+ # calling reader methods on the store instead of using
19
+ # additional refinement arguments.
20
+ #
21
+ # Returns self (i.e. is a chainable method).
22
+ def using(refinements_store)
23
+ @refinements_store = refinements_store
24
+ self
25
+ end
26
+
27
+ def fetch(option_name, *refinements)
28
+
29
+ option_value = @data.fetch(option_name.to_s) do
30
+ raise KeyError, "key not found #{option_name.to_s.inspect} in #{file}"
31
+ end
32
+
33
+ if option_value.kind_of?(Hash)
34
+ fetch_recursively(option_value, *refinements)
35
+ else
36
+ option_value
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def fetch_recursively(option_value, *refinements)
43
+ keys(option_value).inject(values(option_value)) { |data, key|
44
+ refinement = refinements.shift.to_s
45
+ data.fetch(refinement) do
46
+ refinement = refinements_store.send(key).to_s
47
+ data.fetch(refinement) do
48
+ raise KeyError, "refinement not found #{refinement.inspect} in #{file}"
49
+ end
50
+ end
51
+ }
52
+ end
53
+
54
+ def keys(option_value)
55
+
56
+ option_value.fetch('key', '').split(',')
57
+ end
58
+
59
+ def values(option_value)
60
+ option_value.fetch('values') do
61
+ raise KeyError, "key not found \"values\" in #{file}"
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,3 @@
1
+ module Bathysphere
2
+ VERSION = '1.0.0'.freeze
3
+ end
@@ -0,0 +1,6 @@
1
+ ---
2
+ display_name:
3
+ key: 'size'
4
+ large: 'kangaroo'
5
+ medium: 'wombat'
6
+ small: 'possum'
@@ -0,0 +1,6 @@
1
+ ---
2
+ display_name:
3
+ values:
4
+ large: 'kangaroo'
5
+ medium: 'wombat'
6
+ small: 'possum'
@@ -0,0 +1,16 @@
1
+ ---
2
+ display_name:
3
+ key: 'size,color'
4
+ values:
5
+ small:
6
+ green: 'Grape'
7
+ orange: 'Kumquat'
8
+ purple: 'Blueberry'
9
+ medium:
10
+ green: 'Pear'
11
+ orange: 'Orange'
12
+ purple: 'Plum'
13
+ large:
14
+ green: 'Watermelon'
15
+ orange: 'Melon'
16
+ purple: 'Eggplant'
@@ -0,0 +1,2 @@
1
+ ---
2
+ display_name: 'Mountain'
@@ -0,0 +1,118 @@
1
+ require 'spec_helper'
2
+
3
+ module Bathysphere
4
+ describe Parser do
5
+
6
+ let(:file) { 'spec/fixtures/fruit.yml' }
7
+ let(:parser) { Parser.new(file) }
8
+
9
+ it { expect(parser).to respond_to :fetch }
10
+ it { expect(parser).to respond_to :using }
11
+
12
+ describe '#fetch' do
13
+
14
+ context 'when built from a valid YAML file' do
15
+
16
+ context 'with deeply nested properties' do
17
+
18
+ let(:file) { 'spec/fixtures/fruit.yml' }
19
+
20
+ context 'when the property is available' do
21
+
22
+ it 'returns its value' do
23
+ expect(parser.fetch(:display_name, :large, :purple)).to eq 'Eggplant'
24
+ end
25
+ end
26
+
27
+ context 'when the property is not available' do
28
+
29
+ it 'raises KeyError and mentions the parsed file in the message' do
30
+ expect{ parser.fetch(:weight, :large, :purple) }.to raise_error KeyError, Regexp.new(file)
31
+ end
32
+ end
33
+
34
+ context 'when a property of the path is not available' do
35
+
36
+ it 'raises KeyError and mentions the parsed file in the message' do
37
+ expect{ parser.fetch(:weight, :tiny, :purple) }.to raise_error KeyError, Regexp.new(file)
38
+ end
39
+ end
40
+ end
41
+
42
+ context 'with deeply nested values but no :key' do
43
+
44
+ let(:file) { 'spec/fixtures/deeply_nested_with_no_key.yml' }
45
+
46
+ it 'treats the nested hash as the property value' do
47
+ expect{ parser.fetch(:display_name, :large) }.not_to raise_error
48
+ expect(parser.fetch(:display_name, :large)).to eq({ 'large' => 'kangaroo', 'medium' => 'wombat', 'small' => 'possum' })
49
+ end
50
+ end
51
+
52
+ context 'with deeply nested properties, a :key but no :values' do
53
+
54
+ let(:file) { 'spec/fixtures/deeply_nested_with_a_key_but_no_values.yml' }
55
+
56
+ it 'raises KeyError and mentions the parsed file in the message' do
57
+ expect{ parser.fetch(:display_name, :large) }.to raise_error KeyError, Regexp.new(file)
58
+ end
59
+ end
60
+
61
+ context 'with no deeply nested properties' do
62
+
63
+ let(:file) { 'spec/fixtures/simple.yml' }
64
+
65
+ context 'when the property is available' do
66
+
67
+ it 'returns its value (as Hash#fetch does)' do
68
+ expect(parser.fetch(:display_name)).to eq 'Mountain'
69
+ end
70
+ end
71
+
72
+ context 'when the property is not available' do
73
+
74
+ it 'raises KeyError and mentions the parsed file in the message' do
75
+ expect{ parser.fetch(:weight) }.to raise_error KeyError, Regexp.new(file)
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ describe '#using' do
83
+
84
+ let(:refinements_store) { double }
85
+
86
+ it 'is chainable' do
87
+ expect(parser.using(refinements_store)).to be_instance_of Parser
88
+ end
89
+ end
90
+
91
+ context 'when both the :size and :color refinements are required' do
92
+
93
+ let(:file) { 'spec/fixtures/fruit.yml' }
94
+
95
+ context 'and #using(refinements_store)' do
96
+
97
+ let(:refinements_store) { double }
98
+ let(:parser) { Parser.new(file).using(refinements_store) }
99
+
100
+ context 'when the refinements_store implements the :size and :color readers' do
101
+
102
+ before(:each) do
103
+ allow(refinements_store).to receive(:size).and_return(:large)
104
+ allow(refinements_store).to receive(:color).and_return(:purple)
105
+ end
106
+
107
+ describe '#fetch' do
108
+
109
+ it 'returns the property value as expected with no need of custom refinements' do
110
+ expect(parser.fetch(:display_name)).to eq('Eggplant')
111
+ end
112
+
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ describe Bathysphere do
4
+
5
+ it 'has a version number' do
6
+ expect(Bathysphere::VERSION).not_to be nil
7
+ end
8
+ end
@@ -0,0 +1,2 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'bathysphere'
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bathysphere
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Redbubble
8
+ - Gonzalo Bulnes Guilpain
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2017-01-17 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: aruba
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: 0.14.0
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: 0.14.0
28
+ - !ruby/object:Gem::Dependency
29
+ name: cucumber
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '2.0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '2.0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rake
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '10.0'
49
+ - - "<"
50
+ - !ruby/object:Gem::Version
51
+ version: '12'
52
+ type: :development
53
+ prerelease: false
54
+ version_requirements: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: '10.0'
59
+ - - "<"
60
+ - !ruby/object:Gem::Version
61
+ version: '12'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rspec
64
+ requirement: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ type: :development
70
+ prerelease: false
71
+ version_requirements: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ description: Bathysphere takes benefit of a self-describing YAML-based data format
77
+ to normalize options fetching, so the same option can be stored at different depths
78
+ in distinct configuration files.
79
+ email:
80
+ - developers@redbubble.com
81
+ - gonzalo.bulnes@redbubble.com
82
+ executables: []
83
+ extensions: []
84
+ extra_rdoc_files: []
85
+ files:
86
+ - Gemfile
87
+ - LICENSE
88
+ - README.md
89
+ - Rakefile
90
+ - doc/README.md
91
+ - doc/redbubble.png
92
+ - lib/bathysphere.rb
93
+ - lib/bathysphere/parser.rb
94
+ - lib/bathysphere/version.rb
95
+ - spec/fixtures/deeply_nested_with_a_key_but_no_values.yml
96
+ - spec/fixtures/deeply_nested_with_no_key.yml
97
+ - spec/fixtures/fruit.yml
98
+ - spec/fixtures/simple.yml
99
+ - spec/lib/bathysphere/parser_spec.rb
100
+ - spec/lib/bathysphere_spec.rb
101
+ - spec/spec_helper.rb
102
+ homepage: https://github.com/redbubble/bathysphere.git
103
+ licenses:
104
+ - MIT
105
+ metadata: {}
106
+ post_install_message:
107
+ rdoc_options: []
108
+ require_paths:
109
+ - lib
110
+ required_ruby_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ required_rubygems_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ requirements: []
121
+ rubyforge_project:
122
+ rubygems_version: 2.4.5.1
123
+ signing_key:
124
+ specification_version: 4
125
+ summary: Fetch arbitrarily deep properties from YAML files without loosing your breath.
126
+ test_files:
127
+ - spec/fixtures/deeply_nested_with_a_key_but_no_values.yml
128
+ - spec/fixtures/deeply_nested_with_no_key.yml
129
+ - spec/fixtures/fruit.yml
130
+ - spec/fixtures/simple.yml
131
+ - spec/lib/bathysphere/parser_spec.rb
132
+ - spec/lib/bathysphere_spec.rb
133
+ - spec/spec_helper.rb