nested_config 0.2.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/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ rdoc
6
+ tmp
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm 1.9.3@nested_config --create
data/.simplecov ADDED
@@ -0,0 +1,7 @@
1
+ require 'simplecov-rcov'
2
+
3
+ SimpleCov.coverage_dir "tmp/coverage"
4
+ SimpleCov.formatter = SimpleCov::Formatter::RcovFormatter if ENV['CI']
5
+ SimpleCov.start do
6
+ add_filter '/test/'
7
+ end
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem 'simplecov', :require => false
7
+ gem 'simplecov-rcov', :require => false
8
+ end
data/README.rdoc ADDED
@@ -0,0 +1,76 @@
1
+ = nested_config
2
+
3
+ Simple, static, nested application configuration
4
+
5
+ == Usage
6
+
7
+ require 'nested_config'
8
+
9
+ class MyApp
10
+ def self.configure
11
+ yield config
12
+ end
13
+
14
+ def self.config
15
+ @config ||= MyConfig.new
16
+ end
17
+
18
+ class MyConfig < NestedConfig.new
19
+ end
20
+ end
21
+
22
+ === Basic
23
+
24
+ MyApp.configure do |config|
25
+ config.coins = 1000
26
+ config.user do |user|
27
+ user.max = 5
28
+ end
29
+ config.queue do |queue|
30
+ queue.workers do |workers|
31
+ workers.max = 2
32
+ workers.timeout = 60.seconds
33
+ end
34
+ end
35
+ end
36
+
37
+ MyApp.config.coins # => 1000
38
+ MyApp.config.queue.workers.timeout # => 60
39
+
40
+
41
+ === EvaluateOnce
42
+
43
+ With the module +EvaluateOnce+ you can define config value which will be evaluated lazily. Once.
44
+
45
+ class MyConfig
46
+ include NestedConfig::EvaluateOnce
47
+ end
48
+
49
+ MyApp.configure do |config|
50
+ config.country_list = proc { Country.all }
51
+ end
52
+
53
+ MyApp.config.country_list # => [List of countries]
54
+ MyApp.config.country_list # => [List of countries] (cached)
55
+
56
+ The initial access to key +country_list+ calls (via +call+ method) the proc and replaces the value.
57
+ Subsequent calls just fetch the replaced value.
58
+
59
+
60
+ === Key names
61
+
62
+ *Note*: NestedConfig is not a blank slate so you CANNOT use defined method names as keys like +object_id+.
63
+
64
+ == Installation
65
+
66
+ gem install nested_config
67
+
68
+ == Test
69
+
70
+ rake test
71
+ COVERAGE=1 rake test
72
+
73
+ == Release
74
+
75
+ edit lib/nested_config/version.rb
76
+ rake release
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ desc 'Default: run unit tests.'
4
+ task :default => :test
5
+
6
+ # Test
7
+ require 'rake/testtask'
8
+ Rake::TestTask.new(:test) do |test|
9
+ test.test_files = FileList.new('test/*_test.rb')
10
+ test.libs << 'test'
11
+ test.verbose = true
12
+ end
13
+
14
+ # RDoc
15
+ require 'rdoc/task'
16
+ RDoc::Task.new(:rdoc) do |rdoc|
17
+ rdoc.rdoc_dir = 'rdoc'
18
+ rdoc.title = 'nested config'
19
+ rdoc.options << '--line-numbers'
20
+ rdoc.rdoc_files.include('README.rdoc')
21
+ rdoc.rdoc_files.include('lib/**/*.rb')
22
+ end
@@ -0,0 +1,30 @@
1
+ class NestedConfig
2
+ # Evaluates a config value once replacing the original value
3
+ # if the value responds to method +call+.
4
+ #
5
+ # == Example
6
+ #
7
+ # class MyConfig < NestedConfig
8
+ # include NestedConfig::EvaluateOnce
9
+ # end
10
+ #
11
+ # config = MyConfig.new
12
+ # config.startup_time = proc { Time.now }
13
+ # config.env = proc { |env| env.to_s.upcase }
14
+ #
15
+ # config.startup_time # => 2012-06-05 15:57:36 +0200
16
+ # config.startup_time # => 2012-06-05 15:57:36 +0200
17
+ #
18
+ # config.env(:development) # => DEVELOPMENT
19
+ # config.env # => DEVELOPMENT
20
+ module EvaluateOnce
21
+ def [](key, *args)
22
+ value = super
23
+ if value.respond_to?(:call)
24
+ self[key] = value.call(*args)
25
+ else
26
+ value
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,3 @@
1
+ class NestedConfig
2
+ VERSION = "0.2.0"
3
+ end
@@ -0,0 +1,43 @@
1
+ require 'nested_config/version'
2
+
3
+ class NestedConfig
4
+ autoload :EvaluateOnce, 'nested_config/evaluate_once'
5
+
6
+ def initialize
7
+ @hash = {}
8
+ end
9
+
10
+ def [](name, *args)
11
+ @hash[name.to_s]
12
+ end
13
+
14
+ def []=(name, value)
15
+ @hash[name.to_s] = value
16
+ end
17
+
18
+ def __hash__
19
+ @hash
20
+ end
21
+
22
+ def inspect
23
+ @hash
24
+ end
25
+
26
+ def method_missing(name, *args)
27
+ if block_given?
28
+ config = self[name] ||= self.class.new
29
+ yield config
30
+ else
31
+ key = name.to_s.gsub(/=$/, '')
32
+ if $& == '='
33
+ self[key] = args.first
34
+ else
35
+ self[key, *args]
36
+ end
37
+ end
38
+ end
39
+
40
+ def respond_to?(name, include_private=false)
41
+ __hash__.key?(name.to_s) || super
42
+ end
43
+ end
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "nested_config/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "nested_config"
7
+ s.version = NestedConfig::VERSION
8
+ s.authors = ["Peter Suschlik"]
9
+ s.email = ["ps@neopoly.de"]
10
+ s.homepage = "https://github.com/neopoly/nested_config"
11
+ s.summary = %q{Simple, static, nested config}
12
+ s.description = %q{}
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.require_paths = ["lib"]
18
+
19
+ s.add_development_dependency "rake"
20
+ s.add_development_dependency "minitest"
21
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,15 @@
1
+ # simplecov
2
+ require 'simplecov' if ENV['COVERAGE']
3
+
4
+ require 'rubygems'
5
+ require 'minitest/spec'
6
+ require 'minitest/autorun'
7
+
8
+ require 'nested_config'
9
+
10
+ class NestedConfigSpec < MiniTest::Spec
11
+ class << self
12
+ alias :test :it
13
+ alias :context :describe
14
+ end
15
+ end
@@ -0,0 +1,42 @@
1
+ require 'helper'
2
+
3
+ class NestedConfigEvaluateOnceTest < NestedConfigSpec
4
+ let(:config) do
5
+ Class.new(NestedConfig) do
6
+ include NestedConfig::EvaluateOnce
7
+ end.new
8
+ end
9
+
10
+ context "evaluates once w/o argument" do
11
+ context "w/o argument" do
12
+ before do
13
+ config.startup_time = proc { Time.now }
14
+ end
15
+
16
+ test "has time value" do
17
+ assert_instance_of Time, config.startup_time
18
+ end
19
+
20
+ test "value does not change" do
21
+ n = config.startup_time
22
+ assert_same n, config.startup_time
23
+ end
24
+ end
25
+
26
+ context "with argument" do
27
+ before do
28
+ config.env = proc { |e| e.to_s.upcase }
29
+ config.env(:development)
30
+ end
31
+
32
+ test "replaces original value" do
33
+ assert_equal "DEVELOPMENT", config.env
34
+ end
35
+
36
+ test "value does not change" do
37
+ env = config.env
38
+ assert_same env, config.env
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,42 @@
1
+ require 'helper'
2
+
3
+ class NestedConfigEvaluateOnceTest < NestedConfigSpec
4
+ let(:config) do
5
+ Class.new(NestedConfig) do
6
+ include NestedConfig::EvaluateOnce
7
+ end.new
8
+ end
9
+
10
+ context "evaluates once w/o argument" do
11
+ context "w/o argument" do
12
+ before do
13
+ config.startup_time = proc { Time.now }
14
+ end
15
+
16
+ test "has time value" do
17
+ assert_instance_of Time, config.startup_time
18
+ end
19
+
20
+ test "value does not change" do
21
+ n = config.startup_time
22
+ assert_same n, config.startup_time
23
+ end
24
+ end
25
+
26
+ context "with argument" do
27
+ before do
28
+ config.env = proc { |e| e.to_s.upcase }
29
+ config.env(:development)
30
+ end
31
+
32
+ test "replaces original value" do
33
+ assert_equal "DEVELOPMENT", config.env
34
+ end
35
+
36
+ test "value does not change" do
37
+ env = config.env
38
+ assert_same env, config.env
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,128 @@
1
+ require 'helper'
2
+
3
+ class NestedConfigTest < NestedConfigSpec
4
+
5
+ context "basic" do
6
+ let(:config) { NestedConfig.new }
7
+
8
+ test "empty" do
9
+ assert config.__hash__.empty?
10
+ end
11
+
12
+ test "is NOT a blank slate right now" do
13
+ Object.instance_methods.each do |method|
14
+ assert config.respond_to?(method)
15
+ end
16
+ end
17
+
18
+ test "inspect retrives __hash__" do
19
+ c = config.tap { |c| c.foo = :bar }
20
+ assert_same c.inspect, c.__hash__
21
+ end
22
+
23
+ test "cannot use defined method names as keys" do
24
+ c = config.tap do |c|
25
+ c.object_id = :foo
26
+ c.class = :bar
27
+ end
28
+ refute_equal :foo, c.object_id
29
+ refute_equal :bar, c.class
30
+ end
31
+
32
+ test "sets values" do
33
+ c = config.tap do |c|
34
+ c.foo = :bar
35
+ c.bar = :baz
36
+ end
37
+
38
+ assert_equal :bar, c.foo
39
+ assert_equal :baz, c.bar
40
+ assert_nil c.unknown
41
+ end
42
+
43
+ test "sets deep values" do
44
+ c = config.tap do |c|
45
+ c.deep do |deep|
46
+ deep.key = :foo
47
+ deep.deeper do |deeper|
48
+ deeper.key = :bar
49
+ end
50
+ end
51
+ c.deep2 do |deep2|
52
+ deep2.key = :baz
53
+ end
54
+ end
55
+
56
+ assert_equal :foo, c.deep.key
57
+ assert_equal :bar, c.deep.deeper.key
58
+ assert_equal :baz, c.deep2.key
59
+ end
60
+
61
+ test "sets arrays as value" do
62
+ c = config.tap do |c|
63
+ c.ary = [ :foo, :bar ]
64
+ c.ary2 = :foo, :bar
65
+ end
66
+
67
+ assert_equal [ :foo, :bar ], c.ary
68
+ assert_equal [ :foo, :bar ], c.ary2
69
+ end
70
+
71
+ test "cannot nest nil" do
72
+ c = config.tap do |c|
73
+ c.key = :foo
74
+ end
75
+
76
+ e = assert_raises NoMethodError do
77
+ c.deep.deeper.key
78
+ end
79
+ assert_match /NilClass/, e.message
80
+ end
81
+
82
+ test "respond_to?" do
83
+ c = config.tap do |c|
84
+ c.foo = :bar
85
+ end
86
+
87
+ assert_respond_to c, :foo
88
+ end
89
+
90
+ test "re-use already defined nested config" do
91
+ c = config.tap do |c|
92
+ c.users do |users|
93
+ users.max = 23
94
+ end
95
+ c.users do |users|
96
+ users.min = 5
97
+ end
98
+ end
99
+
100
+ assert_equal 23, c.users.max
101
+ assert_equal 5, c.users.min
102
+ end
103
+
104
+ context "subclass" do
105
+ let(:subclassed_config) do
106
+ Class.new(NestedConfig) do
107
+ def foo?
108
+ :bar!
109
+ end
110
+ end.new
111
+ end
112
+
113
+ test "has foo?" do
114
+ assert_equal :bar!, subclassed_config.foo?
115
+ end
116
+
117
+ test "nests subclassed config" do
118
+ c = subclassed_config.tap do |c|
119
+ c.users do |users|
120
+ users.max = 23
121
+ end
122
+ end
123
+
124
+ assert_equal :bar!, c.users.foo?
125
+ end
126
+ end
127
+ end
128
+ end
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nested_config
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Peter Suschlik
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-06-26 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: minitest
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: ''
47
+ email:
48
+ - ps@neopoly.de
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - .gitignore
54
+ - .rvmrc
55
+ - .simplecov
56
+ - Gemfile
57
+ - README.rdoc
58
+ - Rakefile
59
+ - lib/nested_config.rb
60
+ - lib/nested_config/evaluate_once.rb
61
+ - lib/nested_config/version.rb
62
+ - nested_config.gemspec
63
+ - test/helper.rb
64
+ - test/neopoly_config_evaluate_once_test.rb
65
+ - test/nested_config_evaluate_once_test.rb
66
+ - test/nested_config_test.rb
67
+ homepage: https://github.com/neopoly/nested_config
68
+ licenses: []
69
+ post_install_message:
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ! '>='
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ requirements: []
86
+ rubyforge_project:
87
+ rubygems_version: 1.8.24
88
+ signing_key:
89
+ specification_version: 3
90
+ summary: Simple, static, nested config
91
+ test_files: []