configoro 1.0.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/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ -fs --color
data/Gemfile ADDED
@@ -0,0 +1,17 @@
1
+ source :rubygems
2
+
3
+ gem 'rails', '>= 3.0'
4
+ #gem 'activesupport', '>= 3.0'
5
+
6
+ group :development do
7
+ # SPECS
8
+ gem 'rspec'
9
+
10
+ # DOCS
11
+ gem 'yard'
12
+ gem 'RedCloth'
13
+
14
+ # LIBRARIES
15
+ gem 'bundler'
16
+ gem 'jeweler'
17
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,92 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ RedCloth (4.2.7)
5
+ abstract (1.0.0)
6
+ actionmailer (3.0.7)
7
+ actionpack (= 3.0.7)
8
+ mail (~> 2.2.15)
9
+ actionpack (3.0.7)
10
+ activemodel (= 3.0.7)
11
+ activesupport (= 3.0.7)
12
+ builder (~> 2.1.2)
13
+ erubis (~> 2.6.6)
14
+ i18n (~> 0.5.0)
15
+ rack (~> 1.2.1)
16
+ rack-mount (~> 0.6.14)
17
+ rack-test (~> 0.5.7)
18
+ tzinfo (~> 0.3.23)
19
+ activemodel (3.0.7)
20
+ activesupport (= 3.0.7)
21
+ builder (~> 2.1.2)
22
+ i18n (~> 0.5.0)
23
+ activerecord (3.0.7)
24
+ activemodel (= 3.0.7)
25
+ activesupport (= 3.0.7)
26
+ arel (~> 2.0.2)
27
+ tzinfo (~> 0.3.23)
28
+ activeresource (3.0.7)
29
+ activemodel (= 3.0.7)
30
+ activesupport (= 3.0.7)
31
+ activesupport (3.0.7)
32
+ arel (2.0.9)
33
+ builder (2.1.2)
34
+ diff-lcs (1.1.2)
35
+ erubis (2.6.6)
36
+ abstract (>= 1.0.0)
37
+ git (1.2.5)
38
+ i18n (0.5.0)
39
+ jeweler (1.6.0)
40
+ bundler (~> 1.0.0)
41
+ git (>= 1.2.5)
42
+ rake
43
+ mail (2.2.19)
44
+ activesupport (>= 2.3.6)
45
+ i18n (>= 0.4.0)
46
+ mime-types (~> 1.16)
47
+ treetop (~> 1.4.8)
48
+ mime-types (1.16)
49
+ polyglot (0.3.1)
50
+ rack (1.2.2)
51
+ rack-mount (0.6.14)
52
+ rack (>= 1.0.0)
53
+ rack-test (0.5.7)
54
+ rack (>= 1.0)
55
+ rails (3.0.7)
56
+ actionmailer (= 3.0.7)
57
+ actionpack (= 3.0.7)
58
+ activerecord (= 3.0.7)
59
+ activeresource (= 3.0.7)
60
+ activesupport (= 3.0.7)
61
+ bundler (~> 1.0)
62
+ railties (= 3.0.7)
63
+ railties (3.0.7)
64
+ actionpack (= 3.0.7)
65
+ activesupport (= 3.0.7)
66
+ rake (>= 0.8.7)
67
+ thor (~> 0.14.4)
68
+ rake (0.8.7)
69
+ rspec (2.5.0)
70
+ rspec-core (~> 2.5.0)
71
+ rspec-expectations (~> 2.5.0)
72
+ rspec-mocks (~> 2.5.0)
73
+ rspec-core (2.5.2)
74
+ rspec-expectations (2.5.0)
75
+ diff-lcs (~> 1.1.2)
76
+ rspec-mocks (2.5.0)
77
+ thor (0.14.6)
78
+ treetop (1.4.9)
79
+ polyglot (>= 0.3.1)
80
+ tzinfo (0.3.27)
81
+ yard (0.6.8)
82
+
83
+ PLATFORMS
84
+ ruby
85
+
86
+ DEPENDENCIES
87
+ RedCloth
88
+ bundler
89
+ jeweler
90
+ rails (>= 3.0)
91
+ rspec
92
+ yard
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Tim Morgan
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
12
+ included 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
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.textile ADDED
@@ -0,0 +1,96 @@
1
+ h1. Configoro -- Environment-specific configuration data for Rails apps
2
+
3
+ | *Author* | Tim Morgan |
4
+ | *Version* | 1.0 (May 5, 2011) |
5
+ | *License* | Released under the MIT license. |
6
+
7
+ h2. About
8
+
9
+ Pretty much every Rails app out there needs to store environment-specific
10
+ configuration data: API URLs, Memcache settings, AWS keys, etc. The "quick fix"
11
+ approach is usually to dump this information in, e.g., @development.rb@ as
12
+ constants, like @MAILCHIMP_API_URL@. This creates cluttered and unorganized
13
+ environment files.
14
+
15
+ Configoro creates a configuration object that can be accessed as both a hash and
16
+ struct. It stores common configuration data merged with environment-specific
17
+ data.
18
+
19
+ The data is read from YAML files stored alongside the environment files.
20
+
21
+ h2. Installation
22
+
23
+ To use this gem, simply add
24
+
25
+ <pre><code>
26
+ gem 'configoro'
27
+ </code></pre>
28
+
29
+ to your Gemfile, then run
30
+
31
+ <pre><code>
32
+ rails generate configoro
33
+ </code></pre>
34
+
35
+ to install some default configuration files. Edit these new files with your
36
+ configuration data.
37
+
38
+ h2. Usage
39
+
40
+ Assume your application namespace is @MyApp@ (which is what it
41
+ would be if you had created your Rails project using @rails new my_app@). You
42
+ can find your namespace in your @config/application.rb@ file.
43
+
44
+ In this case, you would access your configuration using the
45
+ @MyApp::Configuration@ object. You can access it as an indifferent hash
46
+
47
+ <pre><code>
48
+ MyApp::Configuration[:mailchimp_api_url]
49
+ MyApp::Configuration['mailchimp_api_url']
50
+ </code></pre>
51
+
52
+ or as a struct.
53
+
54
+ <pre><code>
55
+ MyApp::Configuration.mailchimp_api_url
56
+ </code></pre>
57
+
58
+ If you include any hashes in your configuration YAML files, they will also be
59
+ accessible as indifferent hashes or structs:
60
+
61
+ <pre><code>
62
+ MyApp::Configuration.memcache.timeout
63
+ MyApp::Configuration[:memcache]['timeout']
64
+ MyApp::Configuration['memcache'].timeout
65
+ </code></pre>
66
+
67
+ h2. Configuration Files
68
+
69
+ Configuration is stored within the @config/environments@ directory of your Rails
70
+ app. Files ending in ".yml" are loaded from the @common/@ subdirectory and a
71
+ subdirectory named after the current environment.
72
+
73
+ Each file goes into its own hash in the configuration. For example, if you
74
+ placed a file called @memcache.yml@ within @config/environments/development@,
75
+ you would be able to access your Memcache timeout using
76
+ @MyApp::Configuration.memcache.timeout@.
77
+
78
+ h3. Custom Configuration Locations
79
+
80
+ If you need to do your own configuration loading, you can do so using the
81
+ {Configoro::Hash#<<} method. For example, you could place the following in a
82
+ Ruby file under @config/initializers@:
83
+
84
+ <pre><code>
85
+ MyApp::Configuration << "path/to/additional/yaml_file.yml"
86
+ MyApp::Configuration << { 'additional' => 'configuration' }
87
+
88
+ MyApp::Configuration.additional #=> 'configuration'
89
+ </code></pre>
90
+
91
+ Note that if you pass a path to a YAML file, a key will be created to store the
92
+ contents of the file, named after the file name. If the key already exists, the
93
+ new values will be deep-merged into the existing values.
94
+
95
+ In the example above, the data in the @yaml_file.yml@ file can be accessed using
96
+ @MyApp::Configuration.yaml_file@.
data/Rakefile ADDED
@@ -0,0 +1,58 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+
5
+ #################################### BUNDLER ###################################
6
+
7
+ require 'bundler'
8
+ begin
9
+ Bundler.setup(:default, :development)
10
+ rescue Bundler::BundlerError => e
11
+ $stderr.puts e.message
12
+ $stderr.puts "Run `bundle install` to install missing gems"
13
+ exit e.status_code
14
+ end
15
+ require 'rake'
16
+
17
+ #################################### JEWELER ###################################
18
+
19
+ require 'jeweler'
20
+ Jeweler::Tasks.new do |gem|
21
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
22
+ gem.name = "configoro"
23
+ gem.homepage = "http://github.com/RISCfuture/configoro"
24
+ gem.license = "MIT"
25
+ gem.summary = %Q{Configuration object and YAML-based storage for Rails apps}
26
+ gem.description = %Q{Creates a YourApp::Configuration object whose methods are generated from environment-specific YAML files.}
27
+ gem.email = "git@timothymorgan.info"
28
+ gem.authors = [ "Tim Morgan" ]
29
+ # dependencies defined in Gemfile
30
+ end
31
+ Jeweler::RubygemsDotOrgTasks.new
32
+
33
+ ##################################### RSPEC ####################################
34
+
35
+ require 'rspec/core'
36
+ require 'rspec/core/rake_task'
37
+ RSpec::Core::RakeTask.new(:spec) do |spec|
38
+ spec.pattern = FileList['spec/**/*_spec.rb']
39
+ end
40
+
41
+ task :default => :spec
42
+
43
+ ##################################### YARD #####################################
44
+
45
+ require 'yard'
46
+ YARD::Rake::YardocTask.new do |doc|
47
+ doc.options << "-m" << "textile"
48
+ doc.options << "--protected"
49
+ doc.options << "--no-private"
50
+ doc.options << "-r" << "README.textile"
51
+ doc.options << "-o" << "doc"
52
+ doc.options << "--title" << "Configoro Documentation"
53
+
54
+ doc.files = [ 'lib/**/*', 'README.textile' ]
55
+ end
56
+
57
+ desc "Generate API documentation"
58
+ task :doc => :yard
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
data/configoro.gemspec ADDED
@@ -0,0 +1,76 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{configoro}
8
+ s.version = "1.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Tim Morgan"]
12
+ s.date = %q{2011-05-05}
13
+ s.description = %q{Creates a YourApp::Configuration object whose methods are generated from environment-specific YAML files.}
14
+ s.email = %q{git@timothymorgan.info}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.textile"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".rspec",
22
+ "Gemfile",
23
+ "Gemfile.lock",
24
+ "LICENSE.txt",
25
+ "README.textile",
26
+ "Rakefile",
27
+ "VERSION",
28
+ "configoro.gemspec",
29
+ "generators/configoro_generator.rb",
30
+ "lib/configoro.rb",
31
+ "lib/configoro/base.rb",
32
+ "lib/configoro/hash.rb",
33
+ "lib/configoro/railtie.rb",
34
+ "spec/configoro/hash_spec.rb",
35
+ "spec/configoro_spec.rb",
36
+ "spec/data/config/environments/common/basic.yml",
37
+ "spec/data/config/environments/common/hash_test.yml",
38
+ "spec/data/config/environments/development/basic.yml",
39
+ "spec/data/config/environments/development/hash_test.yml",
40
+ "spec/data/config/environments/production/basic.yml",
41
+ "spec/spec_helper.rb"
42
+ ]
43
+ s.homepage = %q{http://github.com/RISCfuture/configoro}
44
+ s.licenses = ["MIT"]
45
+ s.require_paths = ["lib"]
46
+ s.rubygems_version = %q{1.7.2}
47
+ s.summary = %q{Configuration object and YAML-based storage for Rails apps}
48
+
49
+ if s.respond_to? :specification_version then
50
+ s.specification_version = 3
51
+
52
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
53
+ s.add_runtime_dependency(%q<rails>, [">= 3.0"])
54
+ s.add_development_dependency(%q<rspec>, [">= 0"])
55
+ s.add_development_dependency(%q<yard>, [">= 0"])
56
+ s.add_development_dependency(%q<RedCloth>, [">= 0"])
57
+ s.add_development_dependency(%q<bundler>, [">= 0"])
58
+ s.add_development_dependency(%q<jeweler>, [">= 0"])
59
+ else
60
+ s.add_dependency(%q<rails>, [">= 3.0"])
61
+ s.add_dependency(%q<rspec>, [">= 0"])
62
+ s.add_dependency(%q<yard>, [">= 0"])
63
+ s.add_dependency(%q<RedCloth>, [">= 0"])
64
+ s.add_dependency(%q<bundler>, [">= 0"])
65
+ s.add_dependency(%q<jeweler>, [">= 0"])
66
+ end
67
+ else
68
+ s.add_dependency(%q<rails>, [">= 3.0"])
69
+ s.add_dependency(%q<rspec>, [">= 0"])
70
+ s.add_dependency(%q<yard>, [">= 0"])
71
+ s.add_dependency(%q<RedCloth>, [">= 0"])
72
+ s.add_dependency(%q<bundler>, [">= 0"])
73
+ s.add_dependency(%q<jeweler>, [">= 0"])
74
+ end
75
+ end
76
+
@@ -0,0 +1,17 @@
1
+ require 'rails'
2
+ require 'rails/generators'
3
+
4
+ class ConfigoroGenerator < Rails::Generators::Base
5
+ desc "Installs example configuration files for use with Configoro"
6
+
7
+ def create_yaml_files
8
+ create_file "config/environments/common/example.yml",
9
+ { 'common_setting' => true }.to_yaml
10
+ create_file "config/environments/development/example.yml",
11
+ { 'environment_name' => 'Development' }.to_yaml
12
+ create_file "config/environments/test/example.yml",
13
+ { 'environment_name' => 'Test' }.to_yaml
14
+ create_file "config/environments/production/example.yml",
15
+ { 'environment_name' => 'Production' }.to_yaml
16
+ end
17
+ end
data/lib/configoro.rb ADDED
@@ -0,0 +1,10 @@
1
+ raise "Configoro must be used in the context of a Rails 3 application" unless defined?(Rails)
2
+
3
+ require 'yaml'
4
+ require 'bundler'
5
+ Bundler.setup
6
+
7
+ require 'configoro/base'
8
+ require 'configoro/hash'
9
+ require 'configoro/railtie'
10
+ require "#{File.dirname __FILE__}/../generators/configoro_generator"
@@ -0,0 +1,34 @@
1
+ # This module handles initialization of the Configoro object, and contains some
2
+ # utility methods.
3
+
4
+ module Configoro
5
+
6
+ # @return [Module] The Rails application namespace; e.g., @MyApp@ for a Rails
7
+ # app named @MyApp::Application@.
8
+
9
+ def self.namespace
10
+ Object.const_get Rails.application.class.to_s.split('::').first
11
+ end
12
+
13
+ # Creates the configuration dictionary and stores it under
14
+ # @MyApp::Configuration@ (assuming an application named @MyApp@).
15
+
16
+ def self.initialize
17
+ namespace.const_set :Configuration, build_hash(Rails.env)
18
+ end
19
+
20
+ private
21
+
22
+ def self.build_hash(env)
23
+ config = Hash.new
24
+
25
+ load_data config, 'common'
26
+ load_data config, env
27
+
28
+ config
29
+ end
30
+
31
+ def self.load_data(config, env)
32
+ Dir.glob("#{Rails.root}/config/environments/#{env}/*.yml").sort.each { |file| config << file }
33
+ end
34
+ end
@@ -0,0 +1,131 @@
1
+ require 'active_support/hash_with_indifferent_access'
2
+ require 'active_support/core_ext/hash/deep_merge'
3
+
4
+ class Configoro::Hash < HashWithIndifferentAccess
5
+
6
+ # @private
7
+ def initialize(hsh={})
8
+ if hsh.kind_of?(::Hash) then
9
+ super()
10
+ update hsh
11
+ else
12
+ super
13
+ end
14
+ end
15
+
16
+ # Deep-merges additional hash entries into this hash.
17
+ #
18
+ # @return [Configoro::Hash] This object.
19
+ # @overload <<(hash)
20
+ # Adds the entries from another hash.
21
+ # @param [::Hash] hash The additional keys to add.
22
+ # @overload <<(path)
23
+ # Adds the entries from a YAML file. The entries will be added under a
24
+ # sub-hash named after the YAML file's name.
25
+ # @param [String] path The path to a YAML file ending in ".yml".
26
+ # @raise [ArgumentError] If the filename does not end in ".yml".
27
+
28
+ def <<(hsh_or_path)
29
+ case hsh_or_path
30
+ when String
31
+ raise ArgumentError, "Only files ending in .yml can be added" unless File.extname(hsh_or_path) == '.yml'
32
+ return self unless File.exist?(hsh_or_path)
33
+ data = YAML.load_file(hsh_or_path)
34
+ deep_merge! File.basename(hsh_or_path, ".yml") => data
35
+ when ::Hash
36
+ deep_merge! hsh_or_path
37
+ end
38
+ end
39
+
40
+ alias_method :push, :<<
41
+
42
+ # @private
43
+ def dup
44
+ Hash.new(self)
45
+ end
46
+
47
+ # Recursively merges this hash with another hash. All nested hashes are forced
48
+ # to be @Configoro::Hash@ instances.
49
+ #
50
+ # @param [::Hash] other_hash The hash to merge into this one.
51
+ # @return [Configoro::Hash] This object.
52
+
53
+ def deep_merge!(other_hash)
54
+ other_hash.each_pair do |k, v|
55
+ tv = self[k]
56
+ self[k] = if v.kind_of?(::Hash) then
57
+ if tv.kind_of?(::Hash) then
58
+ Configoro::Hash.new(tv).deep_merge!(v)
59
+ else
60
+ Configoro::Hash.new(v)
61
+ end
62
+ else
63
+ v
64
+ end
65
+ end
66
+ self
67
+ end
68
+
69
+ # @private
70
+ #
71
+ # To optimize access, we create a getter method every time we encounter a
72
+ # key that exists in the hash. If the key is later deleted, the method will
73
+ # be removed.
74
+
75
+ def method_missing(meth, *args)
76
+ if include?(meth.to_s) then
77
+ if args.empty? then
78
+ create_getter meth
79
+ else
80
+ raise ArgumentError, "wrong number of arguments (#{args.size} for 0)"
81
+ end
82
+ else
83
+ super
84
+ end
85
+ end
86
+
87
+ # @private
88
+ def inspect
89
+ "#{to_hash.inspect}:#{self.class.to_s}"
90
+ end
91
+
92
+ protected
93
+
94
+ def self.new_from_hash_copying_default(hash)
95
+ Configoro::Hash.new(hash).tap do |new_hash|
96
+ new_hash.default = hash.default
97
+ end
98
+ end
99
+
100
+ def convert_value(value)
101
+ if value.is_a?(::Hash)
102
+ self.class.new_from_hash_copying_default(value)
103
+ elsif value.is_a?(Array)
104
+ value.dup.replace(value.map { |e| convert_value(e) })
105
+ else
106
+ value
107
+ end
108
+ end
109
+
110
+ private
111
+
112
+ def create_getter(meth)
113
+ singleton_class.send(:define_method, meth) do
114
+ if include?(meth.to_s) then
115
+ self[meth.to_s]
116
+ else
117
+ remove_getter meth
118
+ end
119
+ end
120
+
121
+ self[meth.to_s]
122
+ end
123
+
124
+ def remove_getter(meth)
125
+ if methods.include?(meth.to_sym) then
126
+ instance_eval "undef #{meth.to_sym.inspect}"
127
+ end
128
+
129
+ raise NameError, "undefined local variable or method `#{meth}' for #{self.inspect}"
130
+ end
131
+ end
@@ -0,0 +1,7 @@
1
+ # Loads the @Configuration@ object during the Rails initialization process.
2
+
3
+ class Configoro::Railtie < Rails::Railtie
4
+ initializer "Configoro" do
5
+ Configoro.initialize
6
+ end
7
+ end
@@ -0,0 +1,101 @@
1
+ require 'spec_helper'
2
+
3
+ describe Configoro::Hash do
4
+ subject { Configoro::Hash.new(:string => 'value', :fixnum => 123, :hash => { :foo => 'bar' }, :array => [ 1, 2, 3 ]) }
5
+
6
+ context "[getters]" do
7
+ it "should allow access by symbol" do
8
+ subject[:string].should eql('value')
9
+ end
10
+
11
+ it "should allow access by string" do
12
+ subject['fixnum'].should eql(123)
13
+ end
14
+
15
+ it "should allow access by method" do
16
+ subject.array.should eql([ 1, 2, 3 ])
17
+ end
18
+ end
19
+
20
+ context "[accessor methods]" do
21
+ it "should define an accessor method upon first access" do
22
+ subject.methods.should_not include(:string)
23
+ subject.string
24
+ subject.methods.should include(:string)
25
+ end
26
+
27
+ it "should remove the accessor method if the key is removed from the hash" do
28
+ subject.string
29
+ subject.methods.should include(:string)
30
+ subject.delete 'string'
31
+ proc { subject.string }.should raise_error(NameError)
32
+ subject.methods.should_not include(:string)
33
+ end
34
+
35
+ it "should not override existing methods" do
36
+ subject['inspect'] = 'wrong!'
37
+ subject.inspect.should_not eql('wrong!')
38
+ end
39
+ end
40
+
41
+ describe "#include?" do
42
+ it "should accept symbols" do
43
+ subject.should include(:string)
44
+ subject.should_not include(:string2)
45
+ end
46
+
47
+ it "should accept strings" do
48
+ subject.should include('fixnum')
49
+ subject.should_not include('fixnum2')
50
+ end
51
+ end
52
+
53
+ describe "#<<" do
54
+ subject { Configoro::Hash.new }
55
+
56
+ it "should deep-merge entries from a hash" do
57
+ subject << { :a => 'b', :b => { :c => 'd' } }
58
+ subject << { :a => 'b', :b => { :d => 'e' } }
59
+
60
+ subject.a.should eql('b')
61
+ subject.b.c.should eql('d')
62
+ subject.b.d.should eql('e')
63
+ end
64
+
65
+ it "should load a YAML file and deep-merge its entries" do
66
+ subject << "#{File.dirname __FILE__}/../data/config/environments/common/hash_test.yml"
67
+ subject << "#{File.dirname __FILE__}/../data/config/environments/development/hash_test.yml"
68
+
69
+ subject.hash_test.akey.should eql('value')
70
+ subject.hash_test.subhash.key1.should eql('val1')
71
+ subject.hash_test.subhash.key2.should eql('newval')
72
+ end
73
+
74
+ it "should raise an error if the file is not a YAML file" do
75
+ lambda { subject << "example.txt" }.should raise_error(ArgumentError)
76
+ end
77
+
78
+ it "should not change the receiver if the file doesn't exist" do
79
+ subject << "example.yml"
80
+ subject.should be_empty
81
+ end
82
+ end
83
+
84
+ describe "#deep_merge!" do
85
+ subject { Configoro::Hash.new }
86
+
87
+ it "should merge in keys and values" do
88
+ subject['a'] = 'old'
89
+ subject.deep_merge! :a => 'new'
90
+ subject.a.should eql('new')
91
+ end
92
+
93
+ it "should deep-merge sub-hashes and convert them to Configoro::Hashes" do
94
+ subject['hsh'] = { 'key1' => 'val1', 'key2' => 'val2' }
95
+ subject.deep_merge! :hsh => { 'key2' => 'newval' }
96
+
97
+ subject.hsh.key1.should eql('val1')
98
+ subject.hsh.key2.should eql('newval')
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ module MyApp; end
4
+
5
+ describe Configoro do
6
+ subject { MyApp::Configuration }
7
+
8
+ describe "#initialize" do
9
+ it "should make the configuration available to MyApp::Configuration" do
10
+ subject.should be_kind_of(Configoro::Hash)
11
+ end
12
+
13
+ it "should load data from the config files" do
14
+ subject.basic.common_only.should eql('common')
15
+ end
16
+
17
+ it "should give priority to environment-specific files" do
18
+ subject.basic.env_name.should eql('development')
19
+ end
20
+
21
+ it "should not load data from other environments" do
22
+ subject.basic['should_not_exist'].should be_nil
23
+ end
24
+
25
+ it "should convert hashes recursively" do
26
+ subject.hash_test.akey.should eql('value')
27
+ end
28
+
29
+ it "should deep-merge hashes" do
30
+ subject.hash_test.subhash.key1.should eql('val1')
31
+ subject.hash_test.subhash.key2.should eql('newval')
32
+ end
33
+
34
+ it "should not complain when there is no directory for the current environment" do
35
+ Rails.stub!(:env).and_return('unknown')
36
+ Configoro.initialize
37
+ MyApp::Configuration.should eql({"basic"=>{"common_only"=>"common", "env_name"=>"common"}, "hash_test"=>{"akey"=>"value", "subhash"=>{"key1"=>"val1", "key2"=>"val2"}}})
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,3 @@
1
+ ---
2
+ common_only: common
3
+ env_name: common
@@ -0,0 +1,5 @@
1
+ ---
2
+ akey: value
3
+ subhash:
4
+ key1: val1
5
+ key2: val2
@@ -0,0 +1,5 @@
1
+ ---
2
+ :env_name: development
3
+ hsh:
4
+ subhash:
5
+ key2: newval
@@ -0,0 +1,3 @@
1
+ ---
2
+ subhash:
3
+ key2: newval
@@ -0,0 +1,3 @@
1
+ ---
2
+ :env_name: production
3
+ should_not_exist: true
@@ -0,0 +1,23 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+
4
+ require 'bundler'
5
+ Bundler.require :development
6
+
7
+ require 'yaml'
8
+ Bundler.setup
9
+
10
+ require 'configoro/base'
11
+ require 'configoro/hash'
12
+
13
+ # Requires supporting files with custom matchers and macros, etc,
14
+ # in ./support/ and its subdirectories.
15
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
16
+
17
+ RSpec.configure do |config|
18
+ config.before :each do
19
+ application = mock('Rails.application', :class => 'MyApp::Application')
20
+ ::Rails = mock('Rails', :application => application, :env => 'development', :root => File.join(File.dirname(__FILE__), 'data'))
21
+ Configoro.initialize
22
+ end
23
+ end
metadata ADDED
@@ -0,0 +1,144 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: configoro
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 1.0.0
6
+ platform: ruby
7
+ authors:
8
+ - Tim Morgan
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-05-05 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rails
17
+ requirement: &id001 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: "3.0"
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
27
+ name: rspec
28
+ requirement: &id002 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: *id002
37
+ - !ruby/object:Gem::Dependency
38
+ name: yard
39
+ requirement: &id003 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: "0"
45
+ type: :development
46
+ prerelease: false
47
+ version_requirements: *id003
48
+ - !ruby/object:Gem::Dependency
49
+ name: RedCloth
50
+ requirement: &id004 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: "0"
56
+ type: :development
57
+ prerelease: false
58
+ version_requirements: *id004
59
+ - !ruby/object:Gem::Dependency
60
+ name: bundler
61
+ requirement: &id005 !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: "0"
67
+ type: :development
68
+ prerelease: false
69
+ version_requirements: *id005
70
+ - !ruby/object:Gem::Dependency
71
+ name: jeweler
72
+ requirement: &id006 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: "0"
78
+ type: :development
79
+ prerelease: false
80
+ version_requirements: *id006
81
+ description: Creates a YourApp::Configuration object whose methods are generated from environment-specific YAML files.
82
+ email: git@timothymorgan.info
83
+ executables: []
84
+
85
+ extensions: []
86
+
87
+ extra_rdoc_files:
88
+ - LICENSE.txt
89
+ - README.textile
90
+ files:
91
+ - .document
92
+ - .rspec
93
+ - Gemfile
94
+ - Gemfile.lock
95
+ - LICENSE.txt
96
+ - README.textile
97
+ - Rakefile
98
+ - VERSION
99
+ - configoro.gemspec
100
+ - generators/configoro_generator.rb
101
+ - lib/configoro.rb
102
+ - lib/configoro/base.rb
103
+ - lib/configoro/hash.rb
104
+ - lib/configoro/railtie.rb
105
+ - spec/configoro/hash_spec.rb
106
+ - spec/configoro_spec.rb
107
+ - spec/data/config/environments/common/basic.yml
108
+ - spec/data/config/environments/common/hash_test.yml
109
+ - spec/data/config/environments/development/basic.yml
110
+ - spec/data/config/environments/development/hash_test.yml
111
+ - spec/data/config/environments/production/basic.yml
112
+ - spec/spec_helper.rb
113
+ homepage: http://github.com/RISCfuture/configoro
114
+ licenses:
115
+ - MIT
116
+ post_install_message:
117
+ rdoc_options: []
118
+
119
+ require_paths:
120
+ - lib
121
+ required_ruby_version: !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ hash: -2726389570801720649
127
+ segments:
128
+ - 0
129
+ version: "0"
130
+ required_rubygems_version: !ruby/object:Gem::Requirement
131
+ none: false
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ version: "0"
136
+ requirements: []
137
+
138
+ rubyforge_project:
139
+ rubygems_version: 1.7.2
140
+ signing_key:
141
+ specification_version: 3
142
+ summary: Configuration object and YAML-based storage for Rails apps
143
+ test_files: []
144
+