configa 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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