configa 0.0.1

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/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in configa.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 fl00r
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,144 @@
1
+ # Configa
2
+
3
+ Configa makes it easier to use multi environment YAML configs.
4
+
5
+ Inspired by [prepor](https://github.com/prepor)
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'configa'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install configa
20
+
21
+ ## Usage
22
+
23
+ ```ruby
24
+ config_file_path = File.expand_path("../config/config.yml", __FILE__)
25
+ config = Configa.new(config_file_path)
26
+ config.mysql.host
27
+ #=> "localhost"
28
+ config.development.mongodb.user
29
+ #=> "pedro"
30
+ config.development.mongodb(:user, :password)
31
+ #=> ["pedro", "password"]
32
+ config.production.root.password
33
+ #=> Error is raised ;)
34
+ ```
35
+
36
+ ## Why anyone needs configa?
37
+
38
+ You can specify in your config file many environments without duplication
39
+
40
+ ```yaml
41
+ mysql:
42
+ adapter: mysql
43
+ encoding: utf8
44
+ host: localhost
45
+ username: root
46
+
47
+ development:
48
+ mysql:
49
+ database: mysql_dev
50
+
51
+ test:
52
+ mysql:
53
+ database: mysql_test
54
+
55
+ production:
56
+ mysql:
57
+ username: admin
58
+ password: strongone
59
+ ```
60
+
61
+ So, it will create `mysql` "node" which will be shared between all of environments:
62
+
63
+ ```ruby
64
+ config.development.mysql.username
65
+ #=> "root"
66
+ config.production.mysql.username
67
+ #=> "admin"
68
+ config.production.mysql(:username, :host)
69
+ #=> ["admin", "localhost"]
70
+ ```
71
+
72
+ Also you can share base templates between multiple nodes of one environment
73
+
74
+ ```yaml
75
+ mysql:
76
+ adapter: mysql
77
+ encoding: utf8
78
+ host: localhost
79
+ username: root
80
+
81
+ development:
82
+ databases:
83
+ users:
84
+ mysql:
85
+ database: users_dev
86
+ blogs:
87
+ mysql:
88
+ database: blogs_dev
89
+ ```
90
+
91
+ ```ruby
92
+ config.development.databases.users.mysql.database
93
+ #=> "users_dev"
94
+ ```
95
+
96
+ ## Sometimes configuration files grows
97
+
98
+ You can create `development.yml`, `staging.yml` or any other file, put it into the same folder as a base config file and Configa will automatically fetch and load it. Also you can use cascade templates. For example in following example you can define `tarantool` namespace, wich will be inherited by `tarantool` namespace in "development" env.
99
+
100
+ ```yaml
101
+ # config.yml
102
+ mysql:
103
+ adapter: mysql
104
+ encoding: utf8
105
+ host: localhost
106
+ username: root
107
+ tarantool:
108
+ host: localhost
109
+ port: 13013
110
+ type: :block
111
+
112
+ # development.yml
113
+ mysql:
114
+ database: my_database
115
+ tarantool:
116
+ type: :em
117
+ videos:
118
+ tarantool:
119
+ space: 1
120
+ users:
121
+ tarantool:
122
+ space: 2
123
+ ```
124
+
125
+ ```ruby
126
+ config = Configa.new("config.yml")
127
+ config.development.mysql.database
128
+ #=> "my_database"
129
+ config.development.mysql.username
130
+ #=> "root"
131
+ config.videos.tarantool.space
132
+ #=> 1
133
+ config.videos.tarantool.type
134
+ #=> :em
135
+
136
+ ```
137
+
138
+ ## Contributing
139
+
140
+ 1. Fork it
141
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
142
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
143
+ 4. Push to the branch (`git push origin my-new-feature`)
144
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require 'rake/testtask'
4
+
5
+ task :default => :spec
6
+
7
+ desc 'Tests'
8
+ Rake::TestTask.new(:spec) do |t|
9
+ t.libs << 'spec'
10
+ t.pattern = 'spec/**/*_spec.rb'
11
+ t.verbose = false
12
+ end
data/configa.gemspec ADDED
@@ -0,0 +1,17 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/configa/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["fl00r"]
6
+ gem.email = ["fl00r@yandex.ru"]
7
+ gem.description = %q{YAML configuration file parser}
8
+ gem.summary = %q{Configa makes it easier to use multi environment YAML configs}
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "configa"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Configa::VERSION
17
+ end
@@ -0,0 +1,3 @@
1
+ module Configa
2
+ VERSION = "0.0.1"
3
+ end
data/lib/configa.rb ADDED
@@ -0,0 +1,101 @@
1
+ require "configa/version"
2
+ require "yaml"
3
+
4
+ module Configa
5
+ extend self
6
+
7
+ def new(path)
8
+ MagicContainer.new(path)
9
+ end
10
+
11
+ class MagicContainer
12
+ def initialize(path)
13
+ @base_extname = File.extname(path)
14
+ @base_env = File.basename(path, @base_extname)
15
+ @base_dir = File.dirname(path)
16
+ @yamls = {}
17
+ @yaml = {}
18
+ parser
19
+ end
20
+
21
+ def parser(env=nil)
22
+ env ||= @base_env
23
+ env = env.to_s
24
+ load_yaml(env)
25
+ @yaml = merge_yamls
26
+ @yaml = magic(@yaml)
27
+ end
28
+
29
+ def load_yaml(env)
30
+ @yamls[env] ||= begin
31
+ path = File.join(@base_dir, env.to_s + @base_extname)
32
+ file = File.read(path)
33
+ yaml = YAML.load(file)
34
+ yaml
35
+ end
36
+ end
37
+
38
+ def merge_yamls
39
+ ymls = @yamls.dup
40
+ base = ymls.delete(@base_env)
41
+ yaml = base
42
+ ymls.each do |env, data|
43
+ yaml[env] = base.merge(data)
44
+ end
45
+ yaml = merge_yaml(yaml)
46
+ ymls.each do |env, data|
47
+ yaml[env] = merge_yaml(yaml[env])
48
+ end
49
+ yaml
50
+ end
51
+
52
+ def merge_yaml(yaml)
53
+ root_keys = yaml.keys
54
+ yaml.each do |k,v|
55
+ next unless Hash === v
56
+ v.each do |key, data|
57
+ if root_keys.include? key
58
+ yaml[k][key] = yaml[key].merge data
59
+ end
60
+ end
61
+ end
62
+ yaml
63
+ end
64
+
65
+ def magic(data)
66
+ data.each do |k,v|
67
+ data.define_singleton_method(k) do |*args|
68
+ if args.any?
69
+ args.map do |arg|
70
+ data[k][arg.to_s]
71
+ end
72
+ else
73
+ data[k]
74
+ end
75
+ end
76
+ data.define_singleton_method(:method_missing) do |name, *args, &blk|
77
+ raise Configa::UnknownKey, "Unknown key '#{name}' for current node. Available keys are: '#{data.keys * '\', \''}'. Current node: #{data.inspect}"
78
+ end
79
+ if Hash === v
80
+ data[k] = magic(v)
81
+ end
82
+ end
83
+ data
84
+ end
85
+
86
+ def method_missing(name, *args, &blk)
87
+ path = File.join(@base_dir, name.to_s + @base_extname)
88
+ unless @yaml[name.to_s] || @yamls[name.to_s]
89
+ if File.exist?(path)
90
+ parser(name)
91
+ end
92
+ end
93
+ @yaml.send(name, *args, &blk)
94
+ rescue
95
+ raise Configa::UnknownEnvironment, "Unknown environment '#{name}', and file '#{path}' doesn't exist also"
96
+ end
97
+ end
98
+
99
+ class UnknownEnvironment < StandardError; end
100
+ class UnknownKey < StandardError; end
101
+ end
data/spec/base.yml ADDED
@@ -0,0 +1,9 @@
1
+ mysql:
2
+ adapter: mysql
3
+ encoding: utf8
4
+ host: localhost
5
+ username: root
6
+
7
+ tarantool:
8
+ host: localhost
9
+ port: 13013
data/spec/config.yml ADDED
@@ -0,0 +1,19 @@
1
+ mysql:
2
+ adapter: mysql
3
+ encoding: utf8
4
+ host: localhost
5
+ username: root
6
+
7
+ development:
8
+ mysql:
9
+ database: mysql_dev
10
+
11
+ test:
12
+ mysql:
13
+ database: mysql_test
14
+
15
+ production:
16
+ mysql:
17
+ database: mysql_prod
18
+ username: admin
19
+ password: strongone
@@ -0,0 +1,72 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe Configa do
5
+
6
+ describe Configa::MagicContainer do
7
+ it "basic test for one file config" do
8
+ path = File.expand_path("../../config.yml", __FILE__)
9
+ configa = Configa::MagicContainer.new(path)
10
+ mysql = configa.instance_variable_get(:"@yaml")["mysql"]
11
+ dev = configa.instance_variable_get(:"@yaml")["development"]
12
+ dev["mysql"]["adapter"].must_equal mysql["adapter"]
13
+ dev["mysql"]["database"].must_equal "mysql_dev"
14
+ end
15
+
16
+ it "basic test for multi file config" do
17
+ path = File.expand_path("../../base.yml", __FILE__)
18
+ configa = Configa::MagicContainer.new(path)
19
+ mysql = configa.mysql
20
+ dev = configa.development
21
+ dev["mysql"]["adapter"].must_equal mysql.adapter
22
+ dev.mysql.database.must_equal "mysql_dev"
23
+ end
24
+
25
+ it "should raise an error" do
26
+ path = File.expand_path("../../base.yml", __FILE__)
27
+ configa = Configa::MagicContainer.new(path)
28
+ proc{configa.staging}.must_raise Configa::UnknownEnvironment
29
+ end
30
+
31
+ it "should raise an error" do
32
+ path = File.expand_path("../../base.yml", __FILE__)
33
+ configa = Configa::MagicContainer.new(path)
34
+ proc{configa.development.sqlite3}.must_raise Configa::UnknownKey
35
+ end
36
+ end
37
+
38
+ describe "one file" do
39
+ before do
40
+ path = File.expand_path("../../config.yml", __FILE__)
41
+ @config = Configa.new(path)
42
+ end
43
+
44
+ it "should parse simple yml" do
45
+ @config.development.mysql.database.must_equal "mysql_dev"
46
+ @config.development(:mysql).must_equal([{"adapter"=>"mysql", "encoding"=>"utf8", "host"=>"localhost", "username"=>"root", "database"=>"mysql_dev"}])
47
+ @config.development.mysql.username.must_equal "root"
48
+ @config.production.mysql.username.must_equal "admin"
49
+ @config.production.mysql(:username, :database).must_equal ["admin", "mysql_prod"]
50
+ @config.development.mysql.must_equal({"database"=>"mysql_dev", "adapter"=>"mysql", "encoding"=>"utf8", "host"=>"localhost", "username"=>"root"})
51
+ end
52
+ end
53
+
54
+ describe "multiple file" do
55
+ before do
56
+ path = File.expand_path("../../base.yml", __FILE__)
57
+ @config = Configa.new(path)
58
+ end
59
+
60
+ it "should parse simple yml" do
61
+ @config.development.mysql.database.must_equal "mysql_dev"
62
+ @config.development(:mysql).must_equal([{"adapter"=>"mysql", "encoding"=>"utf8", "host"=>"localhost", "username"=>"root", "database"=>"mysql_dev"}])
63
+ @config.development.mysql.username.must_equal "root"
64
+ @config.production.mysql.username.must_equal "admin"
65
+ @config.production.mysql(:username, :database).must_equal ["admin", "mysql_prod"]
66
+ @config.development.mysql.must_equal({"database"=>"mysql_dev", "adapter"=>"mysql", "encoding"=>"utf8", "host"=>"localhost", "username"=>"root"})
67
+ @config.development.users.tarantool.space.must_equal 1
68
+ @config.development.users.tarantool.port.must_equal 13013
69
+ @config.development.users.tarantool.host.must_equal "212.11.3.1"
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,14 @@
1
+ mysql:
2
+ database: mysql_dev
3
+
4
+ tarantool:
5
+ host: "212.11.3.1"
6
+ type: :em
7
+
8
+ users:
9
+ tarantool:
10
+ space: 1
11
+
12
+ posts:
13
+ tarantool:
14
+ space: 2
@@ -0,0 +1,4 @@
1
+ mysql:
2
+ database: mysql_prod
3
+ username: admin
4
+ password: strongone
@@ -0,0 +1,3 @@
1
+ require 'configa'
2
+ require 'minitest/spec'
3
+ require 'minitest/autorun'
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: configa
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - fl00r
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-09-05 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: YAML configuration file parser
15
+ email:
16
+ - fl00r@yandex.ru
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - .gitignore
22
+ - Gemfile
23
+ - LICENSE
24
+ - README.md
25
+ - Rakefile
26
+ - configa.gemspec
27
+ - lib/configa.rb
28
+ - lib/configa/version.rb
29
+ - spec/base.yml
30
+ - spec/config.yml
31
+ - spec/configa/configa_spec.rb
32
+ - spec/development.yml
33
+ - spec/production.yml
34
+ - spec/spec_helper.rb
35
+ homepage: ''
36
+ licenses: []
37
+ post_install_message:
38
+ rdoc_options: []
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ none: false
49
+ requirements:
50
+ - - ! '>='
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ requirements: []
54
+ rubyforge_project:
55
+ rubygems_version: 1.8.23
56
+ signing_key:
57
+ specification_version: 3
58
+ summary: Configa makes it easier to use multi environment YAML configs
59
+ test_files:
60
+ - spec/base.yml
61
+ - spec/config.yml
62
+ - spec/configa/configa_spec.rb
63
+ - spec/development.yml
64
+ - spec/production.yml
65
+ - spec/spec_helper.rb