aerogel-configurator 1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 37d55037f2ea026955b18c93343504f4e0860f42
4
+ data.tar.gz: 01170bb9b27c66b10f1e1bf8359c7a2303a0c811
5
+ SHA512:
6
+ metadata.gz: 688ef787aa153a283fe9e3870a37c98d7290e59235f7d7ba7154279c2c0c609f7e02bf7402564dc9e2e177cff097d6354da37b294b27722baa481d5e8c927d7b
7
+ data.tar.gz: 45c2d6452816b27b0b3fe3a91d844d847d879a0db30c5200d281ad4e42f6f7b04521c24dabe0fcc9dfa5c5a4ea5ac0ce77914636fa257ef8dcb0566c4b896199
data/.gitignore ADDED
@@ -0,0 +1,20 @@
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
18
+ *.sublime-project
19
+ *.sublime-workspace
20
+ .rspec
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in configurator.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Alex Kukushkin
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,65 @@
1
+ # Configurator
2
+
3
+ Configuration files for Ruby applications made easy.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'rb-configurator'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install rb-configurator
18
+
19
+ ## Usage
20
+
21
+ Configuration parameters as chain:
22
+
23
+ config = Configurator.load "my.conf"
24
+
25
+ config.group.a # => 1
26
+
27
+ Configuration is a HASH:
28
+
29
+ config = Configurator.load "my.conf"
30
+
31
+ config['group'] # => { :a => 1, :b => 2 }
32
+
33
+ Store your configuration in the separate file(s) using simple DSL:
34
+
35
+ # my.conf
36
+ foo "hello"
37
+ bar 42
38
+ a_group {
39
+ boolean_param true
40
+ a_nested_group {
41
+ inner bar
42
+ ar_var [1, 2, "three"]
43
+ }
44
+ }
45
+
46
+
47
+ Load configuration file(s) in your application:
48
+
49
+ require 'configurator'
50
+ config = Configurator.load "my.conf"
51
+
52
+ # Access settings:
53
+ puts config.foo # => "hello"
54
+ puts config.a_group.a_nested_group.inner # => 42
55
+
56
+
57
+ TODO: Write usage instructions here
58
+
59
+ ## Contributing
60
+
61
+ 1. Fork it
62
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
63
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
64
+ 4. Push to the branch (`git push origin my-new-feature`)
65
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ desc "Run tests"
4
+ task :default do
5
+ system "bundle exec rspec"
6
+ end
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'aerogel/configurator/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "aerogel-configurator"
8
+ spec.version = Configurator::VERSION
9
+ spec.authors = ["Alex Kukushkin"]
10
+ spec.email = ["alex@kukushk.in"]
11
+ spec.summary = %q{Simple configuration files for Ruby applications}
12
+ spec.description = %q{Store your application configuration in separate files using simple DSL or YAML. Access your configuration settings in a simple way}
13
+ spec.homepage = "https://github.com/kukushkin/aerogel-configurator"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ end
data/examples/ex1.rb ADDED
@@ -0,0 +1,7 @@
1
+ require 'aerogel/configurator'
2
+
3
+ config = Configurator.new
4
+
5
+ config.a.foo.bar = "hello"
6
+
7
+ puts "config: #{config.to_hash}"
data/examples/ex2.conf ADDED
@@ -0,0 +1,5 @@
1
+ a {
2
+ foo {
3
+ bar "hello"
4
+ }
5
+ }
data/examples/ex2.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'aerogel/configurator'
2
+
3
+
4
+ config = Configurator.load File.dirname( __FILE__ )+"/ex2.conf"
5
+
6
+ puts "config: #{config.to_hash}"
@@ -0,0 +1,4 @@
1
+ require "aerogel/configurator/version"
2
+ require "aerogel/configurator/configurator"
3
+ require "aerogel/configurator/parameter"
4
+ require "aerogel/configurator/dsl"
@@ -0,0 +1,59 @@
1
+
2
+ class Configurator
3
+
4
+ attr_accessor :params
5
+ # alias_method :to_hash, :params
6
+
7
+ # Creates a Configurator object and set default parameters.
8
+ #
9
+ def initialize( opts = {} )
10
+ raise ArgumentError.new("Invalid parameters passed to Configurator.new") unless opts.is_a? Hash
11
+ @params = opts.dup
12
+ end
13
+
14
+
15
+ def method_missing(method, *args)
16
+ # puts "Configurator.method_missing: #{method}"
17
+ Parameter.new( @params ).send method, *args
18
+ end
19
+
20
+ # Loads contents of a configuration file into an existing Configurator object.
21
+ #
22
+ def load( filename )
23
+ filename_contents = File.read filename
24
+ cfg = DSL.new( filename_contents, @params )
25
+ deep_merge( @params, cfg.params )
26
+ end
27
+
28
+ # Clears parameters
29
+ #
30
+ def clear!
31
+ @params = {}
32
+ end
33
+
34
+ # Creates a Configurator object and loads parameters from given file.
35
+ #
36
+ # Returns a created object with parameters loaded into it.
37
+ #
38
+ def self.load( filename )
39
+ config = self.new {}
40
+ config.load filename
41
+ return config
42
+ end
43
+
44
+ private
45
+
46
+ # Deep merge parameters hash with +other+ hash.
47
+ #
48
+ def deep_merge( left, right )
49
+ right.each do |key, value|
50
+ if value.is_a? Hash
51
+ left[key] ||= {}
52
+ deep_merge( left[key], right[key] )
53
+ else
54
+ left[key] = right[key]
55
+ end
56
+ end
57
+ end
58
+
59
+ end # class Configurator
@@ -0,0 +1,39 @@
1
+ class Configurator
2
+ private
3
+
4
+ class DSL
5
+ attr_accessor :params
6
+
7
+ # +source+ can be either Hash (preprocessed parameters),
8
+ # Block (a nested block to be invoked in a context of the object)
9
+ # or a String (a config file contents to be evaluated in a context of the object)
10
+ def initialize( source, root = nil )
11
+ # @root = root || self
12
+ @params = {}
13
+ @root = root || @params
14
+ if source.is_a? Hash
15
+ @params = source
16
+ elsif source.is_a? String
17
+ self.instance_eval( source )
18
+ else
19
+ self.instance_eval( &source )
20
+ end
21
+ end
22
+
23
+ def method_missing( method, *args, &block )
24
+ if (not block_given?) && (args.empty?)
25
+ # puts "DSL: get '#{method}' params:#{@params}"
26
+ Parameter.new( @root ).send method, *args
27
+ elsif block_given?
28
+ nested_set = DSL.new( block, @root )
29
+ @params[method] = nested_set.params
30
+ elsif args.size > 1
31
+ @params[method] = args
32
+ else
33
+ @params[method] = args.first
34
+ end
35
+ end
36
+
37
+ end # class DSL
38
+ end # class Configurator
39
+
@@ -0,0 +1,80 @@
1
+ class Configurator
2
+ private
3
+ class Parameter
4
+
5
+ def initialize( data = {} )
6
+ @data = data
7
+ end
8
+
9
+ def method_missing(method, *args)
10
+ # puts "Parameter.method_missing: #{method}"
11
+ if method.to_s =~ /=$/
12
+ @data[method.to_s.match(/^(.*)=$/)[1].to_sym] = args.first
13
+ elsif @data[method].is_a?(Hash)
14
+ Parameter.new @data[method]
15
+ elsif @data[method].nil?
16
+ Undefined.new @data, [method]
17
+ elsif @data[method].is_a? Proc
18
+ @data[method].call
19
+ else
20
+ # it's a leaf
21
+ @data[method]
22
+ end
23
+ end
24
+
25
+ def raw
26
+ @data
27
+ end
28
+
29
+ def to_hash
30
+ @data
31
+ end
32
+
33
+ def inspect
34
+ @data.inspect
35
+ end
36
+
37
+ # Undefined is a parameter that was not set yet.
38
+ # It allows accessing its sub-parameters and defines the entire
39
+ # chain once an assignement method on a sub-parameter is called.
40
+ #
41
+ # +root+ is where parameter will be 'mounted' on assignement
42
+ # +name+ is an Array of chained names starting from mount point
43
+ #
44
+ class Undefined
45
+ def initialize( root, name )
46
+ # puts "Undefined.new: root=#{root} name=#{name.to_s} "
47
+ @root = root
48
+ @name = name # convert to array
49
+ end
50
+
51
+ def method_missing(method, *args)
52
+ # puts "Undefined.method_missing: #{method} root=#{@root} names=#{@names}"
53
+ if method.to_s =~ /=$/
54
+ method = method.to_s.match(/^(.*)=$/)[1].to_sym
55
+ # deep assign
56
+ d = ( @root[@name.shift] ||= {} )
57
+ @name.each do |n|
58
+ d = ( d[n] ||= {} )
59
+ end
60
+ d[method] = args.first
61
+ else
62
+ Undefined.new( @root, @name+[method])
63
+ end
64
+ end
65
+
66
+ def defined?; false; end
67
+ def nil?; true; end
68
+ def empty?; true; end
69
+ def to_s; ''; end
70
+ def raw; nil; end
71
+
72
+ # to_ary defined basically to keep rspec happy
73
+ def to_ary; []; end
74
+
75
+ end # class Undefined
76
+
77
+ end # class Parameter
78
+
79
+
80
+ end # class Configurator
@@ -0,0 +1,3 @@
1
+ class Configurator
2
+ VERSION = "1.0.1"
3
+ end
data/spec/conf/a.conf ADDED
@@ -0,0 +1,2 @@
1
+ foo "hello"
2
+ bar 42.0
data/spec/conf/b.conf ADDED
@@ -0,0 +1,10 @@
1
+ # Test for overwriting defaults
2
+ #
3
+
4
+ # will overwrite 'foo'
5
+ foo "hello"
6
+
7
+ # will overwrite only 'group.a'
8
+ group {
9
+ a 123
10
+ }
data/spec/conf/c.conf ADDED
@@ -0,0 +1,7 @@
1
+ # Test: nested groups
2
+
3
+ a {
4
+ b {
5
+ c "foo"
6
+ }
7
+ }
data/spec/conf/d.conf ADDED
@@ -0,0 +1,4 @@
1
+ # Test: deferred parameters
2
+
3
+ foo "fuu" # will be changed to "foo"
4
+ bar lambda{ foo+"bar" } # then bar should be "foobar"
@@ -0,0 +1,118 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+
3
+ describe Configurator do
4
+
5
+ before(:all) do
6
+ @default_params = {
7
+ :foo => "abc",
8
+ :bar => 123,
9
+ :group => {
10
+ :a => 1,
11
+ :b => 2
12
+ }
13
+ }
14
+ end
15
+
16
+ it "should respond to 'load' and return a Configurator instance" do
17
+ Configurator.should respond_to(:load)
18
+ Configurator.load( test_filename( 'conf/a.conf' ) ).should be_instance_of Configurator
19
+ end
20
+
21
+ describe ".new" do
22
+
23
+ it 'should allow no parameters' do
24
+ config = nil
25
+ expect { config = Configurator.new }.to_not raise_error
26
+ config.params.should be_empty # empty Hash
27
+ end
28
+ it 'should accept Hash as a set of default parameters' do
29
+ config = nil
30
+ expect { config = Configurator.new @default_params }.to_not raise_error
31
+ end
32
+ end
33
+
34
+ describe ".load" do
35
+ it "should load parameters from a configuration file" do
36
+ config = Configurator.load( test_filename( 'conf/a.conf' ) )
37
+ config.should be_instance_of Configurator
38
+ config.params.should eql( {:foo=>"hello", :bar=>42.0} )
39
+ end
40
+ end
41
+
42
+ describe "#params" do
43
+ it 'should provide access to raw parameters' do
44
+ config = Configurator.new @default_params
45
+ config.should respond_to(:params)
46
+ config.params.should eql( @default_params )
47
+ end
48
+ end
49
+
50
+ describe "method chaining" do
51
+ it 'should allow access to parameters and nested parameters for retrieval' do
52
+ config = Configurator.new @default_params
53
+ config.foo.should eql "abc"
54
+ config.bar.should eql 123
55
+ config.fuu.should be_nil
56
+ config.group.a.should eql 1
57
+ config.group.b.should eql 2
58
+ config.group.c.should be_nil
59
+ end
60
+ it 'should allow storing new parameters and nested parameters' do
61
+ config = Configurator.new
62
+ config.foo.should be_nil
63
+ expect do
64
+ config.foo = "abc"
65
+ config.bar = 123
66
+ config.group.a = 1
67
+ config.group.b = 2
68
+ end.not_to raise_error
69
+ config.foo.should eql "abc"
70
+ config.bar.should eql 123
71
+ config.fuu.should be_nil
72
+ config.group.a.should eql 1
73
+ config.group.b.should eql 2
74
+ config.group.c.should be_nil
75
+ end
76
+ end
77
+
78
+ describe "instance" do
79
+ it { should respond_to :load }
80
+ it "should load parameters" do
81
+ config = Configurator.new
82
+ config.params.should eql({})
83
+ config.load test_filename( 'conf/a.conf' )
84
+ config.params.should eql( {:foo=>"hello", :bar=>42.0} )
85
+ end
86
+ it "should load and overwrite only defined members" do
87
+ config = Configurator.new @default_params
88
+ config.foo.should eql "abc"
89
+ config.bar.should eql 123
90
+ config.group.a.should eql 1
91
+ config.group.b.should eql 2
92
+ config.load test_filename( 'conf/b.conf' )
93
+ config.foo.should eql "hello"
94
+ config.bar.should eql 123 # not overwritten
95
+ config.group.a.should eql 123
96
+ config.group.b.should eql 2 # not overwritten
97
+ end
98
+
99
+ it { should respond_to :clear! }
100
+ it "should clear all parameters on request" do
101
+ config = Configurator.new @default_params
102
+ config.foo.should eql "abc"
103
+ config.clear!
104
+ config.params.should eql({})
105
+ end
106
+
107
+ it "should respond to #to_hash on each level" do
108
+ config = Configurator.new @default_params
109
+ expect { config.to_hash }.to_not raise_error
110
+ config.to_hash.should be_instance_of Hash
111
+ config.to_hash.should eql @default_params
112
+ config.group.to_hash.should be_instance_of Hash
113
+ config.group.to_hash.should eql @default_params[:group]
114
+ end
115
+
116
+ end
117
+ end # describe Configurator
118
+
@@ -0,0 +1,19 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+
3
+ describe "Configurator::DSL" do
4
+
5
+ it "should allow nested groups" do
6
+ config = Configurator.load test_filename('conf/c.conf')
7
+ config.a.b.c.should eql "foo"
8
+ end
9
+
10
+ it "should handle deferred parameters" do
11
+ config = Configurator.load test_filename('conf/d.conf')
12
+ config.foo.should eql "fuu"
13
+ config.bar.should eql "fuubar"
14
+ config.foo = "foo"
15
+ config.bar.should eql "foobar"
16
+ end
17
+
18
+
19
+ end # describe Configurator::DSL
@@ -0,0 +1,8 @@
1
+ require 'rubygems'
2
+ require 'rspec'
3
+
4
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'aerogel', 'configurator')
5
+
6
+ def test_filename( name )
7
+ File.expand_path( File.join( File.dirname(__FILE__), name ))
8
+ end
metadata ADDED
@@ -0,0 +1,115 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: aerogel-configurator
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Alex Kukushkin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-06-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Store your application configuration in separate files using simple DSL
56
+ or YAML. Access your configuration settings in a simple way
57
+ email:
58
+ - alex@kukushk.in
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - .gitignore
64
+ - Gemfile
65
+ - LICENSE.txt
66
+ - README.md
67
+ - Rakefile
68
+ - aerogel-configurator.gemspec
69
+ - examples/ex1.rb
70
+ - examples/ex2.conf
71
+ - examples/ex2.rb
72
+ - lib/aerogel/configurator.rb
73
+ - lib/aerogel/configurator/configurator.rb
74
+ - lib/aerogel/configurator/dsl.rb
75
+ - lib/aerogel/configurator/parameter.rb
76
+ - lib/aerogel/configurator/version.rb
77
+ - spec/conf/a.conf
78
+ - spec/conf/b.conf
79
+ - spec/conf/c.conf
80
+ - spec/conf/d.conf
81
+ - spec/lib/configurator_spec.rb
82
+ - spec/lib/dsl_spec.rb
83
+ - spec/spec_helper.rb
84
+ homepage: https://github.com/kukushkin/aerogel-configurator
85
+ licenses:
86
+ - MIT
87
+ metadata: {}
88
+ post_install_message:
89
+ rdoc_options: []
90
+ require_paths:
91
+ - lib
92
+ required_ruby_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubyforge_project:
104
+ rubygems_version: 2.0.3
105
+ signing_key:
106
+ specification_version: 4
107
+ summary: Simple configuration files for Ruby applications
108
+ test_files:
109
+ - spec/conf/a.conf
110
+ - spec/conf/b.conf
111
+ - spec/conf/c.conf
112
+ - spec/conf/d.conf
113
+ - spec/lib/configurator_spec.rb
114
+ - spec/lib/dsl_spec.rb
115
+ - spec/spec_helper.rb