yacht 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source :rubygems
2
+
3
+ gemspec
4
+
5
+ gem 'rake'
data/README.rdoc ADDED
@@ -0,0 +1,73 @@
1
+ = Yacht
2
+
3
+ Yacht is an application configuration gem that lets you define settings for multiple environments in YAML files. It is similar to AppConfig[https://github.com/cjbottaro/app_config] with additional features like:
4
+ * use of ClassyStruct for improved performance over OpenStruct
5
+ * protection of sensitive settings by specifying a whitelist in a YAML file
6
+ * easy override of nested keys (not pretty with YAML references)
7
+
8
+ == Installation
9
+
10
+ * <b>Rails</b>:
11
+ Add this to your Gemfile and run the +bundle+ command.
12
+
13
+ gem "yacht"
14
+
15
+ * Outside of rails, just require the gem as usual:
16
+
17
+ require 'rubygems'
18
+ require 'yacht'
19
+
20
+ == Getting Started
21
+
22
+ === Step 1: YAML files
23
+
24
+ First create two (or more) YAML files in the same directory to define your settings:
25
+
26
+ # config/yacht/base.yml (required)
27
+ production:
28
+ cdn_host: 1.2.3.4
29
+ super_secret_info:
30
+ aws_key: foofoo
31
+ twitter_key: barbar
32
+ test:
33
+ cdn_host: localhost
34
+ super_secret_info:
35
+ # you can safely overwrite a single value in a nested key
36
+ # YAML references (& and *) don't let you do this
37
+ # see https://gist.github.com/979804 for an explanation
38
+ aws_key: bazbaz
39
+
40
+ # config/yacht/whitelist.yml (required)
41
+ # any keys specified here can be used as a whitelist filter:
42
+ # YachtLoader.to_hash(:apply_whitelist? => true)
43
+ # (by default the whitelist is ignored)
44
+ - super_secret_info
45
+
46
+ # config/yacht/local.yml (optional)
47
+ # any values set in local.yml will override values set in base.yml
48
+ # useful for development and testing
49
+ production:
50
+ cdn_host: localhost
51
+
52
+ === Step 2: Define a constant
53
+
54
+ * <b>Rails</b>:
55
+ # config/initializers/01_yacht.rb
56
+ # Define a constant that will store all settings
57
+ # looks for the following YAML files:
58
+ # * config/yacht/base.yml
59
+ # * config/yacht/local.yml
60
+ # * config/yacht/whitelist.yml
61
+ Yacht = YachtLoader.to_classy_struct
62
+ # now you can access any key set in your YAML files with:
63
+ # Yacht.my_key
64
+
65
+ * Outside of rails, you need to tell +YachtLoader+ where your YAML files are stored, and what environment you want to use.
66
+ YachtLoader.dir = '/path/to/YAML/dir'
67
+ YachtLoader.environment = 'my_environment'
68
+ Yacht = YachtLoader.to_classy_struct
69
+
70
+
71
+ == How it works
72
+
73
+ Currently, the +Yacht+ gem defines a class called +YachtLoader+ that will read your YAML files and output them as a regular +Hash+ or a +ClassyStruct+ . Then you use <tt>YachtLoader#to_classy_struct</tt> (or <tt>YachtLoader#to_hash</tt>) to define a constant. You can name the constant whatever you like, but you should use +Yacht+. This is because a planned feature is to have +Yacht+ defined when the gem is required and have everything namespaced under a single +Yacht+ class.
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ # encoding: utf-8
2
+ require 'rubygems'
3
+ require 'bundler'
4
+ Bundler.setup
5
+ Bundler::GemHelper.install_tasks
6
+
7
+ Dir['gem_tasks/**/*.rake'].each { |rake| load rake }
8
+
9
+ task :default => [:spec]
@@ -0,0 +1,24 @@
1
+ if !Hash.instance_methods.include?(:deep_merge)
2
+ class Hash
3
+ # copied from ActiveSupport::CoreExtensions::Hash::DeepMerge 2.3.8
4
+ def deep_merge(other_hash)
5
+ self.merge(other_hash) do |key, oldval, newval|
6
+ oldval = oldval.to_hash if oldval.respond_to?(:to_hash)
7
+ newval = newval.to_hash if newval.respond_to?(:to_hash)
8
+ oldval.class.to_s == 'Hash' && newval.class.to_s == 'Hash' ? oldval.deep_merge(newval) : newval
9
+ end
10
+ end
11
+ end
12
+ end
13
+
14
+ if !Hash.instance_methods.include?(:slice)
15
+ class Hash
16
+ # copied from http://as.rubyonrails.org/classes/ActiveSupport/CoreExtensions/Hash/Slice.html
17
+ def slice(*keys)
18
+ allowed = Set.new(respond_to?(:convert_key) ? keys.map { |key| convert_key(key) } : keys)
19
+ hash = {}
20
+ allowed.each { |k| hash[k] = self[k] if has_key?(k) }
21
+ hash
22
+ end
23
+ end
24
+ end
data/lib/yacht.rb ADDED
@@ -0,0 +1,12 @@
1
+ # This file is named yacht.rb
2
+ # so that Bundler will automatically load YachtLoader
3
+ #
4
+ # In the future, once we figure out how to integrate ClassyStruct,
5
+ # YachtLoader will be renamed to Yacht
6
+
7
+ require "yacht_loader/base"
8
+ require "yacht_loader/classy_struct"
9
+ require "yacht_loader/version"
10
+
11
+ require "yacht_loader/rails" if Object.const_defined?(:Rails)
12
+ require 'monkeypatches/hash'
@@ -0,0 +1,112 @@
1
+ # TODO: Rename YachtLoader to Yacht and somehow incorporate ClassyStruct
2
+
3
+ class YachtLoader
4
+ class LoadError < StandardError
5
+ end
6
+
7
+ class << self
8
+ def environment
9
+ @environment ||= 'default'
10
+ end
11
+ attr_writer :environment
12
+
13
+ def dir
14
+ @dir ||= File.join( File.dirname(__FILE__), 'yacht')
15
+ end
16
+ attr_writer :dir
17
+
18
+ def full_file_path_for_config(config_type)
19
+ File.join( self.dir, "#{config_type}.yml" )
20
+ end
21
+
22
+ def config_file_for(config_type)
23
+ raise LoadError.new "#{config_type} is not a valid config type" unless valid_config_types.include?(config_type.to_s)
24
+
25
+ full_file_path_for_config(config_type)
26
+ end
27
+
28
+ def valid_config_types
29
+ %w( base local whitelist )
30
+ end
31
+
32
+ def all
33
+ chain_configs(base_config, self.environment).deep_merge(local_config)
34
+ end
35
+
36
+ def to_hash(opts={})
37
+ opts[:apply_whitelist?] = false unless opts.has_key?(:apply_whitelist?)
38
+ self.environment = opts[:env] if opts.has_key?(:env)
39
+
40
+ if opts[:apply_whitelist?]
41
+ all.slice(*whitelist)
42
+ else
43
+ all
44
+ end
45
+ end
46
+
47
+ def whitelist
48
+ load_config_file(:whitelist, :expect_to_load => Array) || begin
49
+ raise LoadError.new("Couldn't load whitelist")
50
+ end
51
+ end
52
+
53
+ def base_config
54
+ load_config_file(:base) || begin
55
+ raise LoadError.new("Couldn't load base config")
56
+ end
57
+ end
58
+
59
+ def local_config
60
+ load_config_file(:local, :require_presence? => false) || {}
61
+ end
62
+
63
+ protected
64
+ def load_config_file(file_type, opts={})
65
+ # by default, expect a Hash to be loaded
66
+ expected_class = opts[:expect_to_load] || Hash
67
+
68
+ # by default, raise error if file missing or empty
69
+ presence_required = if opts.has_key?(:require_presence?)
70
+ opts[:require_presence?]
71
+ else
72
+ true
73
+ end
74
+
75
+ file_name = self.config_file_for(file_type)
76
+
77
+ loaded = if File.exists?(file_name)
78
+ YAML.load( File.read(file_name) )
79
+ else
80
+ nil
81
+ end
82
+
83
+ # an empty YAML file will be converted to boolean false
84
+ raise LoadError.new "#{file_name} cannot be empty" if presence_required && loaded === false
85
+
86
+ # YAML contained the wrong type
87
+ raise LoadError.new "#{file_name} must contain #{expected_class} (got #{loaded.class})" if loaded && !loaded.is_a?(expected_class)
88
+
89
+ loaded
90
+ rescue => e
91
+ # don't do anything to our own custom errors
92
+ if e.is_a? YachtLoader::LoadError
93
+ raise e
94
+ else
95
+ # convert other errors to YachtLoader::LoadError
96
+ raise LoadError.new "ERROR: loading config file: '#{file_type}': #{e}"
97
+ end
98
+ end
99
+
100
+ def chain_configs(config, env)
101
+ raise LoadError.new "environment '#{env}' does not exist" unless config.has_key?(env)
102
+
103
+ parent = if config[env]['_parent']
104
+ chain_configs(config, config[env]['_parent'])
105
+ else
106
+ config['default'] || {}
107
+ end
108
+
109
+ parent.deep_merge(config[env])
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,15 @@
1
+ require 'classy_struct'
2
+
3
+ class YachtLoader
4
+ class << self
5
+ def classy_struct_instance
6
+ @classy_struct_instance ||= ClassyStruct.new
7
+ end
8
+
9
+ def to_classy_struct(opts={})
10
+ classy_struct_instance.new( self.to_hash(opts) )
11
+ rescue StandardError => e
12
+ raise LoadError.new("Error creating ClassyStruct: #{e.message}")
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ class YachtLoader
2
+ class << self
3
+ # use the current rails environment by default
4
+ def environment
5
+ @environment ||= Rails.env
6
+ end
7
+
8
+ def dir
9
+ @dir ||= Rails.root.join('config', 'yacht')
10
+ end
11
+
12
+ def full_file_path_for_config(config_type)
13
+ dir.join("#{config_type}.yml")
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,3 @@
1
+ class YachtLoader
2
+ VERSION = "0.1.0"
3
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format nested
@@ -0,0 +1,115 @@
1
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
2
+ $:.unshift(File.dirname(__FILE__))
3
+
4
+ require 'rubygems'
5
+ require 'bundler'
6
+ Bundler.setup
7
+
8
+ # ==============
9
+ # = SimpleCov! =
10
+ # ==============
11
+ require 'simplecov'
12
+ SimpleCov.start
13
+
14
+ require 'yacht'
15
+
16
+ Spec::Runner.configure do |config|
17
+ config.after :each do
18
+ YachtLoader.environment = nil
19
+ YachtLoader.dir = nil
20
+ YachtLoader.instance_variable_set(:@config_file_names, nil)
21
+ end
22
+ end
23
+
24
+ BASE_CONFIG_FILE = <<EOF
25
+ default:
26
+ name: default
27
+ defaultkey: defaultvalue
28
+ dog: schnauzer
29
+ hashkey:
30
+ foo: bar
31
+ baz: wurble
32
+ xyzzy: thud
33
+ an_environment:
34
+ name: an_environment
35
+ hashkey:
36
+ baz: yay
37
+ dog: terrier
38
+ a_child_environment:
39
+ _parent: an_environment
40
+ name: a_child_environment
41
+ hashkey:
42
+ foo: kung
43
+ test:
44
+ baloney: delicious
45
+ EOF
46
+
47
+ WHITELIST_CONFIG_FILE = <<EOF
48
+ - defaultkey
49
+ - hashkey
50
+ EOF
51
+
52
+ EMPTY_WHITELIST_CONFIG_FILE = <<EOF
53
+ EOF
54
+
55
+ INVALID_WHITELIST_CONFIG_FILE = <<EOF
56
+ somenonsenseorother
57
+ EOF
58
+
59
+ LOCAL_CONFIG_FILE = <<EOF
60
+ localkey: localvalue
61
+ EOF
62
+
63
+ EMPTY_LOCAL_CONFIG_FILE = <<EOF
64
+ EOF
65
+
66
+ INVALID_LOCAL_CONFIG_FILE = <<EOF
67
+ someinvalidstufforother
68
+ EOF
69
+
70
+
71
+ # ===================================
72
+ # = Helpers to mock file operations =
73
+ # ===================================
74
+ def banish_config_file_from_prefix(prefix)
75
+ file_name = YachtLoader.config_file_for(prefix)
76
+ banish_file(file_name)
77
+ end
78
+
79
+ # shortcut to mock config file
80
+ def conjure_config_file_from_prefix(prefix, file_contents=nil)
81
+ file_name = YachtLoader.config_file_for(prefix)
82
+ file_contents ||= "#{prefix.upcase}_CONFIG_FILE".constantize
83
+
84
+ conjure_file(file_name, file_contents)
85
+ end
86
+
87
+ def conjure_bad_config_file_from_prefix(prefix)
88
+ file_name = "#{prefix}_config_file"
89
+ file_contents = file_name.upcase.constantize
90
+
91
+ conjure_file(file_name, file_contents)
92
+ end
93
+
94
+ # mock file existence & contents
95
+ def conjure_file(file_name, file_contents)
96
+ File.stub!(:exists?).with(file_name).and_return true
97
+ File.stub!(:read).with(file_name).and_return file_contents
98
+ end
99
+
100
+ # mock file non-existence
101
+ def banish_file(file_name)
102
+ File.stub!(:exists?).with(file_name).and_return(false)
103
+ File.stub!(:read).with(file_name).and_raise Errno::ENOENT.new("No such file or directory - #{file_name}")
104
+ end
105
+
106
+ # ================================================
107
+ # = Railsy helper to turn strings into constants =
108
+ # ================================================
109
+ if !String.instance_methods.include?(:constantize)
110
+ class String
111
+ def constantize # NOT as awesome as ActiveSupport::Inflector#constantize
112
+ Object.const_get(self)
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,179 @@
1
+ require 'spec_helper'
2
+
3
+ describe YachtLoader do
4
+ before(:each) do
5
+ # mock existence and content of files to avoid file system in specs
6
+ %w(base whitelist local).each do |prefix|
7
+ conjure_config_file_from_prefix(prefix)
8
+ end
9
+
10
+ # stub bad config files to check error handling
11
+ %w(empty_whitelist invalid_whitelist empty_local invalid_local).each do |baddie|
12
+ conjure_bad_config_file_from_prefix(baddie)
13
+ end
14
+ end
15
+
16
+ it "raises an error if base config file is missing" do
17
+ banish_config_file_from_prefix('base')
18
+
19
+ expect {
20
+ YachtLoader.to_hash
21
+ }.to raise_error( YachtLoader::LoadError, /Couldn't load base config/)
22
+ end
23
+
24
+ context "whitelist" do
25
+ it "loads keys into an Array" do
26
+ YachtLoader.whitelist.should == ["defaultkey", "hashkey"]
27
+ end
28
+
29
+ it "returns all keys by default, ignoring whitelist" do
30
+ YachtLoader.environment = 'default'
31
+ YachtLoader.to_hash.keys.should include("defaultkey", "hashkey")
32
+ end
33
+
34
+ it "only returns keys included in whitelist when :apply_whitelist? option is true" do
35
+ YachtLoader.environment = 'default'
36
+ YachtLoader.to_hash(:apply_whitelist? => true).keys.should == ["defaultkey", "hashkey"]
37
+ end
38
+
39
+ context "config file" do
40
+ it "raises an error if missing and whitelist is applied" do
41
+ banish_config_file_from_prefix('whitelist')
42
+
43
+ expect {
44
+ YachtLoader.to_hash(:apply_whitelist? => true)
45
+ }.to raise_error( YachtLoader::LoadError, /Couldn't load whitelist/)
46
+ end
47
+
48
+ it "raises an error if empty and whitelist is applied" do
49
+ conjure_config_file_from_prefix( :whitelist, File.read('empty_whitelist_config_file') )
50
+
51
+ expect {
52
+ YachtLoader.to_hash(:apply_whitelist? => true)
53
+ }.to raise_error( YachtLoader::LoadError, /whitelist.+ cannot be empty/)
54
+ end
55
+
56
+ it "raises an error if invalid and whitelist is applied" do
57
+ conjure_config_file_from_prefix( :whitelist, File.read('invalid_whitelist_config_file') )
58
+
59
+ expect {
60
+ YachtLoader.to_hash(:apply_whitelist? => true)
61
+ }.to raise_error( YachtLoader::LoadError, /whitelist.+ must contain Array/)
62
+ end
63
+ end
64
+ end
65
+
66
+ context "checks environment and sets sensible defaults" do
67
+ it "sets the environment to 'default'" do
68
+ YachtLoader.environment.should == "default"
69
+ end
70
+
71
+ it "allows setting the environment by passing an option to `to_hash`" do
72
+ YachtLoader.to_hash(:env => 'a_child_environment')
73
+ YachtLoader.environment.should == 'a_child_environment'
74
+ end
75
+
76
+
77
+ it "raises an error if an environment is requested that doesn't exist" do
78
+ expect {
79
+ YachtLoader.environment = 'nonexistent'
80
+ YachtLoader.to_hash
81
+ }.to raise_error( YachtLoader::LoadError, /does not exist/)
82
+ end
83
+
84
+ it "merges configuration for named environment onto defaults" do
85
+ YachtLoader.environment = 'an_environment'
86
+ YachtLoader.to_hash['defaultkey'].should == 'defaultvalue'
87
+ YachtLoader.to_hash['name'].should == 'an_environment'
88
+ end
89
+ end
90
+
91
+ context "handles child environment" do
92
+ before do
93
+ YachtLoader.environment = 'a_child_environment'
94
+ end
95
+
96
+ it "merges child onto the parent it names" do
97
+ YachtLoader.to_hash['dog'].should == 'terrier'
98
+ end
99
+
100
+ it "merges the hashes recursively" do
101
+ child = YachtLoader.to_hash['hashkey']
102
+
103
+ child['foo'].should == 'kung'
104
+ child['baz'].should == 'yay'
105
+ child['xyzzy'].should == 'thud'
106
+ end
107
+ end
108
+
109
+ context "handling of local config file" do
110
+ before do
111
+ YachtLoader.environment = 'an_environment'
112
+ end
113
+
114
+ it "merges values onto named environment and defaults" do
115
+ YachtLoader.to_hash['defaultkey'].should == 'defaultvalue'
116
+ YachtLoader.to_hash['name'].should == 'an_environment'
117
+ YachtLoader.to_hash['localkey'].should == 'localvalue'
118
+ end
119
+
120
+ it "uses base config if missing" do
121
+ banish_config_file_from_prefix('local')
122
+
123
+ File.should_not_receive(:read).with('local_config_file')
124
+
125
+ YachtLoader.send(:local_config).should == {}
126
+ YachtLoader.to_hash['defaultkey'].should == 'defaultvalue'
127
+ YachtLoader.to_hash['name'].should == 'an_environment'
128
+ end
129
+
130
+ it "uses base config if empty" do
131
+ conjure_config_file_from_prefix(:local, File.read('empty_local_config_file'))
132
+
133
+ File.should_not_receive(:read).with('local_config_file')
134
+
135
+ YachtLoader.send(:local_config).should == {}
136
+ YachtLoader.to_hash['defaultkey'].should == 'defaultvalue'
137
+ YachtLoader.to_hash['name'].should == 'an_environment'
138
+ end
139
+
140
+ it "raises an error if invalid" do
141
+ conjure_config_file_from_prefix( :local, File.read('invalid_local_config_file') )
142
+ expect {
143
+ YachtLoader.to_hash
144
+ }.to raise_error( YachtLoader::LoadError, %r{local.yml must contain Hash})
145
+ end
146
+ end
147
+
148
+ describe :config_file_for do
149
+ it "returns the full file path for the following config files: base, local & whitelist" do
150
+ %w(base local whitelist).each do |config_file|
151
+ YachtLoader.should_receive(:full_file_path_for_config).with(config_file)
152
+
153
+ YachtLoader.config_file_for(config_file)
154
+ end
155
+ end
156
+
157
+ it "raises an error if the config file is not found" do
158
+ expect {
159
+ YachtLoader.config_file_for(:foo)
160
+ }.to raise_error( YachtLoader::LoadError, "foo is not a valid config type")
161
+ end
162
+ end
163
+
164
+ describe :load_config_file do
165
+ it "loads the specified file" do
166
+ conjure_config_file_from_prefix("base", "some contents")
167
+
168
+ YachtLoader.send(:load_config_file, "base", :expect_to_load => String).should == "some contents"
169
+ end
170
+
171
+ it "raises an error if opening the file leads to an exception" do
172
+ YachtLoader.stub(:config_file_for).and_raise(StandardError.new("my_unique_error_message"))
173
+
174
+ expect {
175
+ YachtLoader.send(:load_config_file, "some file")
176
+ }.to raise_error( YachtLoader::LoadError, %r{ERROR: loading.+my_unique_error_message} )
177
+ end
178
+ end
179
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe "to_classy_struct" do
4
+ before do
5
+ conjure_config_file_from_prefix("base")
6
+ conjure_config_file_from_prefix("local")
7
+ conjure_config_file_from_prefix("whitelist")
8
+
9
+ YachtLoader.environment = 'an_environment'
10
+ end
11
+
12
+ it "creates a ClassyStruct based on to_hash" do
13
+ Yacht = YachtLoader.to_classy_struct
14
+ Yacht.dog.should == "terrier"
15
+ end
16
+
17
+ # ClassyStruct improves performance by adding accessors to the instance object
18
+ # If the instance is not reused, there is no advantage to ClassyStruct over OpenStruct
19
+ it "reuses the instance of ClassyStruct on subsequent calls" do
20
+ first_obj = YachtLoader.classy_struct_instance
21
+ second_obj = YachtLoader.classy_struct_instance
22
+
23
+ first_obj.object_id.should == second_obj.object_id.should
24
+ end
25
+
26
+ it "passes options to to_hash" do
27
+ YachtLoader.should_receive(:to_hash).with({:my => :awesome_option})
28
+
29
+ Yacht = YachtLoader.to_classy_struct({:my => :awesome_option})
30
+ end
31
+
32
+ it "raises a custom error if ClassyStruct cannot be created" do
33
+ YachtLoader.stub!(:to_hash).and_raise("some funky error")
34
+
35
+ expect {
36
+ Yacht = YachtLoader.to_classy_struct
37
+ }.to raise_error(YachtLoader::LoadError, /some funky error/)
38
+ end
39
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Rails support" do
4
+ before do
5
+ require "yacht_loader/rails"
6
+ @yacht_dir = "/path/to/rails/config/yacht"
7
+ end
8
+
9
+ describe :environment do
10
+ before do
11
+ Rails = stub("Rails")
12
+ end
13
+ it "uses the current rails environment by default" do
14
+ Rails.should_receive(:env)
15
+
16
+ YachtLoader.environment
17
+ end
18
+ end
19
+
20
+ describe :dir do
21
+ it "uses config/yacht by default" do
22
+ Rails.stub_chain(:root, :join).and_return(@yacht_dir)
23
+
24
+ YachtLoader.dir.should == @yacht_dir
25
+ end
26
+ end
27
+
28
+ describe :full_file_path_for_config do
29
+ it "calls dir.join" do
30
+ fake_dir = stub("dir stub")
31
+ YachtLoader.stub(:dir).and_return(fake_dir)
32
+ fake_dir.should_receive(:join).with("some.yml")
33
+
34
+ YachtLoader.full_file_path_for_config("some")
35
+ end
36
+ end
37
+ end
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: yacht
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.0
6
+ platform: ruby
7
+ authors:
8
+ - Mani Tadayon
9
+ - Rico Rodriquez Collins
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+
14
+ date: 2011-05-18 00:00:00 Z
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: classy_struct
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: 0.3.2
25
+ type: :runtime
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ prerelease: false
30
+ requirement: &id002 !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - "="
34
+ - !ruby/object:Gem::Version
35
+ version: 1.3.1
36
+ type: :development
37
+ version_requirements: *id002
38
+ - !ruby/object:Gem::Dependency
39
+ name: simplecov
40
+ prerelease: false
41
+ requirement: &id003 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - "="
45
+ - !ruby/object:Gem::Version
46
+ version: 0.4.2
47
+ type: :development
48
+ version_requirements: *id003
49
+ description:
50
+ email:
51
+ - mtadayon@atti.com
52
+ - rcollins@atti.com
53
+ executables: []
54
+
55
+ extensions: []
56
+
57
+ extra_rdoc_files: []
58
+
59
+ files:
60
+ - lib/monkeypatches/hash.rb
61
+ - lib/yacht.rb
62
+ - lib/yacht_loader/base.rb
63
+ - lib/yacht_loader/classy_struct.rb
64
+ - lib/yacht_loader/rails.rb
65
+ - lib/yacht_loader/version.rb
66
+ - spec/spec.opts
67
+ - spec/spec_helper.rb
68
+ - spec/yacht_loader/base_spec.rb
69
+ - spec/yacht_loader/classy_struct_spec.rb
70
+ - spec/yacht_loader/rails_spec.rb
71
+ - Gemfile
72
+ - Rakefile
73
+ - README.rdoc
74
+ homepage: https://github.com/attinteractive/yacht
75
+ licenses: []
76
+
77
+ post_install_message:
78
+ rdoc_options: []
79
+
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: "0"
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: 1.3.7
94
+ requirements: []
95
+
96
+ rubyforge_project:
97
+ rubygems_version: 1.7.2
98
+ signing_key:
99
+ specification_version: 3
100
+ summary: Use YAML files to manage application configuration.
101
+ test_files: []
102
+