simpleconf 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,4 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
4
+ Gemfile.lock
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in simpleconf.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,84 @@
1
+ SimpleConf
2
+ =============
3
+
4
+ Needed a simple configuration library for my gems. Made public so everyone can take advantage!
5
+
6
+ ##Install
7
+ [sudo] gem install simpleconf
8
+
9
+ ##Usage
10
+
11
+ **Simple Configuration**
12
+
13
+ CONFIG = SimpleConf {
14
+ host "localhost"
15
+ port 80
16
+ blacklist [1,2,3]
17
+ }
18
+
19
+ CONFIG.host # localhost
20
+ CONFIG.port # 80
21
+ CONFIG.blacklist # [1,2,3]
22
+
23
+ **Nested Configuration**
24
+
25
+ CONFIG = SimpleConf {
26
+ server {
27
+ ip "0.0.0.0"
28
+ port 8080
29
+ }
30
+
31
+ workers 50
32
+
33
+ security {
34
+ admin {
35
+ only_from "127.0.0.1"
36
+ }
37
+
38
+ max_logins 5
39
+ }
40
+ }
41
+
42
+ CONFIG.server.ip # "0.0.0.0"
43
+ CONFIG.workers # 50
44
+ CONFIG.security.admin.only_from # "127.0.0.1"
45
+ CONFIG.security.max_logins # 5
46
+
47
+ **Merging**
48
+
49
+ default = SimpleConf {
50
+ host "localhost"
51
+ port 80
52
+ }
53
+
54
+ new_config = default.merge( #also merge!
55
+ SimpleConf {
56
+ port 9999
57
+ }
58
+ )
59
+
60
+ new_config.host # "localhost"
61
+ new_config.port # 9999
62
+
63
+ **Overriding**
64
+
65
+ config = SimpleConf {
66
+ host "localhost", :override => false
67
+ port 80
68
+ }
69
+
70
+ config.host "google.com"
71
+ config.host # Still "localhost"
72
+ config.port 9999
73
+ config.port # 9999
74
+
75
+ **Lock configuration**
76
+
77
+ default = SimpleConf(:init_only => true){
78
+ host "localhost"
79
+ }
80
+
81
+ default.port 80 #throws error!!!
82
+
83
+
84
+ To see all examples/cases, see the spec file.
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require 'bundler'
2
+ include Rake::DSL
3
+ Bundler::GemHelper.install_tasks
4
+
5
+ require 'rspec/core/rake_task'
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task :default => :spec
9
+ task :test => :spec
data/lib/core/hash.rb ADDED
@@ -0,0 +1,16 @@
1
+ class Hash
2
+ def rmerge!(other_hash)
3
+ merge!(other_hash) do |key, oldval, newval|
4
+ if oldval.is_a?(SimpleConf::Conf) && newval.is_a?(SimpleConf::Conf)
5
+ oldval.check_and_change_overrides(newval)
6
+ oldval.__vars__.rmerge!(newval.__vars__)
7
+ oldval.instance_eval(&newval.__instance_block__)
8
+ oldval
9
+ elsif oldval.is_a?(Hash)
10
+ oldval.rmerge!(newval)
11
+ else
12
+ newval
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,5 @@
1
+ module Kernel
2
+ def SimpleConf(*args, &blk)
3
+ SimpleConf.build(*args, &blk)
4
+ end
5
+ end
@@ -0,0 +1,87 @@
1
+ module SimpleConf
2
+ class Conf < ::BlankSlate
3
+ attr_accessor :__vars__, :__init_only__
4
+ attr_reader :__instance_block__, :__overrides__
5
+ def initialize(instance_block, opts={})
6
+ @__opts__ = opts
7
+ @__vars__ = {}
8
+ @__init_only__ = false
9
+ @__instance_block__ = instance_block
10
+ @__default_config__ = {
11
+ :override => true
12
+ }
13
+
14
+ @__overrides__ = {}
15
+ end
16
+
17
+ def merge(other)
18
+ fail "Other needs to be a SimpleConf::Conf" unless other.is_a? Conf
19
+ copy = SimpleConf.build(@__opts__, &@__instance_block__)
20
+ copy.merge!(other)
21
+ copy
22
+ end
23
+
24
+ def check_and_change_overrides(other)
25
+ self.__overrides__.each do |meth, override|
26
+ if !override
27
+ other.__overrides__[meth] = false
28
+ other.__vars__[meth] = __vars__[meth]
29
+ end
30
+ end
31
+
32
+ end
33
+
34
+ def merge!(other)
35
+ fail "Other needs to be a SimpleConf::Conf" unless other.is_a? Conf
36
+ check_and_change_overrides(other)
37
+ self.__init_only__ = other.__init_only__
38
+ self.instance_eval(&other.__instance_block__)
39
+ __vars__.rmerge!(other.__vars__)
40
+ nil
41
+ end
42
+
43
+ def method_missing(meth, *args, &blk)
44
+ fail "#{meth} was not defined in configuration setup" if @__init_only__
45
+
46
+ meta = (class << self; self; end)
47
+
48
+ if block_given?
49
+ nested_opts = @__opts__.merge(args.shift || {})
50
+ sub_config = SimpleConf.build(nested_opts, &blk)
51
+
52
+ meta.class_eval do
53
+ define_method(meth) do |*args, &blk|
54
+ @__vars__[meth]
55
+ end
56
+ end
57
+ @__vars__[meth] = sub_config
58
+ return
59
+ end
60
+
61
+ value = args.shift
62
+ opts = @__default_config__.merge(args.shift || {})
63
+ @__overrides__[meth] = opts[:override]
64
+ meta.class_eval do
65
+ define_method(meth) do |*args, &blk|
66
+ local_override = ((args[1].is_a?(Hash) && !args[1][:override].nil?) && @__overrides__[meth]) ? args[1][:override] : @__overrides__[meth]
67
+
68
+ @__overrides__[meth] = local_override
69
+
70
+ if args.first && @__overrides__[meth]
71
+ @__vars__[meth] = args.first
72
+ else
73
+ @__vars__[meth]
74
+ end
75
+ end
76
+
77
+ define_method("#{meth}=") do |*args|
78
+ if args.first && @__overrides__[meth]
79
+ @__vars__[meth] = args.first
80
+ end
81
+ @__vars__[meth]
82
+ end
83
+ end
84
+ @__vars__[meth] = value
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,3 @@
1
+ module SimpleConf
2
+ VERSION = "0.0.1"
3
+ end
data/lib/simpleconf.rb ADDED
@@ -0,0 +1,19 @@
1
+ module SimpleConf
2
+ require 'blankslate'
3
+ BlankSlate.reveal(:is_a?)
4
+ require 'simpleconf/conf'
5
+ require 'core/hash'
6
+ require 'core/kernel'
7
+
8
+ def build(opts={}, &blk)
9
+ fail "Build needs a block" unless block_given?
10
+ c = Conf.new(blk, opts)
11
+ c.instance_eval(&blk)
12
+ c.__init_only__ = true if opts[:init_only]
13
+ c
14
+ end
15
+
16
+ module_function :build
17
+
18
+ end
19
+
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "simpleconf/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "simpleconf"
7
+ s.version = SimpleConf::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Mike Lewis"]
10
+ s.email = ["ft.mikelewis@gmail.com"]
11
+ s.homepage = "http://github.com/mikelewis/simpleconf"
12
+ s.summary = %q{Simple Configuration DSL that supports merging, locking and more.}
13
+ s.description = %q{Simple Configuration DSL that supports merging, locking and more.}
14
+
15
+ s.rubyforge_project = "simpleconf"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_development_dependency 'rake'
23
+ s.add_development_dependency 'rspec'
24
+ s.add_development_dependency 'blankslate'
25
+ end
@@ -0,0 +1,411 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleConf do
4
+ context "#build" do
5
+ it "should respond to build" do
6
+ SimpleConf.should respond_to(:build)
7
+ end
8
+
9
+ it "should throw an error if no block given" do
10
+ lambda {
11
+ SimpleConf.build
12
+ }.should raise_error
13
+ end
14
+
15
+ it "should accept a block" do
16
+ lambda {
17
+ SimpleConf.build {}
18
+ }.should_not raise_error
19
+ end
20
+
21
+ it "should return a SimpleConf::Conf" do
22
+ SimpleConf.build{}.should be_an_instance_of(SimpleConf::Conf)
23
+ end
24
+
25
+ it "should return two seperate configs for two calls" do
26
+ c = SimpleConf.build {}
27
+ SimpleConf.build{}.should_not eq(c)
28
+ end
29
+ end
30
+
31
+ it "should create a Kernel method SimpleConf" do
32
+ Kernel.should respond_to(:SimpleConf)
33
+ end
34
+
35
+ it "should of created a recursive merge for hash" do
36
+ meth_name = RUBY_VERSION < "1.9" ? "rmerge!" : :rmerge!
37
+ Hash.instance_methods.should include(meth_name)
38
+ end
39
+
40
+ it "should create a Kernel method that works" do
41
+ c = SimpleConf {
42
+ boat "blue"
43
+ sky "red"
44
+ }
45
+ c.boat.should == "blue"
46
+ c.sky.should == "red"
47
+ end
48
+
49
+ it "should be able to create simple config" do
50
+ c = SimpleConf.build do
51
+ host "localhost"
52
+ port 80
53
+ this_is_blank
54
+ end
55
+
56
+ c.host.should == "localhost"
57
+ c.port.should == 80
58
+ c.this_is_blank.should == nil
59
+ end
60
+
61
+ it "should be able to create a simple config that we can edit" do
62
+ c = SimpleConf.build do
63
+ host "localhost"
64
+ end
65
+ c.host "google.com"
66
+
67
+ c.host.should == "google.com"
68
+ end
69
+
70
+ it "should be able to respond to value= after setup" do
71
+ c = SimpleConf.build do
72
+ host "localhost"
73
+ end
74
+ c.host = "google.com"
75
+ c.host.should == "google.com"
76
+ end
77
+
78
+ context "Blank Slate" do
79
+ it "should remove all methods and allow user to do whatever he wants " do
80
+
81
+ c = SimpleConf {
82
+ id 5
83
+ hash 20
84
+ freeze "boo"
85
+ }
86
+
87
+ c.id.should == 5
88
+ c.hash.should == 20
89
+ c.freeze.should == "boo"
90
+ end
91
+
92
+ end
93
+
94
+ context "init_only" do
95
+ it "should throw an error if we use strict option and we have never encountered that config item" do
96
+ c = SimpleConf.build :init_only => true do
97
+ host "localhost"
98
+ end
99
+ lambda {
100
+ c.port
101
+ }.should raise_error
102
+ end
103
+
104
+ it "should throw an error if we use the strict options and we try to make another config" do
105
+ c = SimpleConf(:init_only=>true) {
106
+ host "localhost"
107
+ }
108
+
109
+ lambda {
110
+ c.port "boooo"
111
+ }.should raise_error
112
+ end
113
+
114
+ it "should not throw an error if we don't use strict option and we have never enounterd that config item" do
115
+ c = SimpleConf.build do
116
+ host "localhost"
117
+ end
118
+ lambda {
119
+ c.port
120
+ }.should_not raise_error
121
+ end
122
+ end
123
+
124
+ context "override" do
125
+ it "should default to true" do
126
+ c = SimpleConf.build do
127
+ host "localhost"
128
+ end
129
+
130
+ c.host "yea"
131
+ c.host.should == "yea"
132
+ end
133
+
134
+ it "should not allow override if specified" do
135
+ c = SimpleConf.build do
136
+ host "localhost", :override => false
137
+ end
138
+
139
+ c.host "bo"
140
+ c.host = "HAHAHA"
141
+ c.host.should == "localhost"
142
+ end
143
+ end
144
+
145
+ context "nested" do
146
+ it "should create nested configs" do
147
+ c = SimpleConf {
148
+ server {
149
+ host "localhost"
150
+ port 80
151
+ }
152
+ }
153
+
154
+ c.server.should respond_to(:host)
155
+ c.server.should respond_to(:port)
156
+ c.server.host.should == "localhost"
157
+ c.server.port.should == 80
158
+ end
159
+
160
+ it "should create nested configs forever" do
161
+ c = SimpleConf {
162
+ a {
163
+ age 15
164
+ b {
165
+ name "Mike"
166
+ c {
167
+ d 5
168
+ }
169
+ }
170
+ }
171
+ }
172
+
173
+ c.a.age.should == 15
174
+ c.a.b.name.should == "Mike"
175
+ c.a.b.c.d.should == 5
176
+ end
177
+
178
+ it "should allow for editable config elems within nests" do
179
+ c = SimpleConf {
180
+ a {
181
+ b {
182
+ name "mike"
183
+ }
184
+ }
185
+ }
186
+ c.a.b.name = "Tim"
187
+
188
+ c.a.b.name.should == "Tim"
189
+ end
190
+
191
+ it "should inherit properties" do
192
+ c = SimpleConf(:init_only => true) {
193
+ a {
194
+ age 15
195
+ }
196
+ }
197
+ c.a.age 20
198
+
199
+ lambda {
200
+ c.a.b
201
+ }.should raise_error
202
+ end
203
+
204
+ it "should allow for options for nests" do
205
+ c = SimpleConf {
206
+ age 15
207
+ a(:init_only=>true) {
208
+ name "Mike"
209
+
210
+ b {
211
+ sex "male"
212
+ race "human", :override => false
213
+ }
214
+ }
215
+ }
216
+
217
+ lambda { c.a.tom }.should raise_error
218
+
219
+ c.age 20
220
+ c.age.should == 20
221
+
222
+ lambda { c.a.b.haha }.should raise_error
223
+
224
+ c.a.b.race "donkey"
225
+ c.a.b.race.should == "human"
226
+
227
+ c.a.b.sex "female"
228
+ c.a.b.sex.should == "female"
229
+ end
230
+
231
+ it "should allow for options within nests" do
232
+ c = SimpleConf {
233
+ a {
234
+ b "Mike", :override => false
235
+ }
236
+ }
237
+
238
+ c.a.b "Tom"
239
+ c.a.b.should == "Mike"
240
+ end
241
+ end
242
+
243
+ context "Merge" do
244
+ before do
245
+ @default = SimpleConf {
246
+ server "localhost"
247
+ port 80
248
+ socket "/tmp/sock.sock"
249
+
250
+ tree {
251
+ leafs 30
252
+ height 50
253
+ bugs false
254
+ ants{
255
+ big false
256
+ fast true
257
+ }
258
+ }
259
+ }
260
+
261
+ @new = SimpleConf {
262
+ port 90
263
+ socket "haha"
264
+ tree {
265
+ leafs 60, :override => false
266
+ bugs true
267
+ ants {
268
+ fast false
269
+ home {
270
+ big true
271
+ sq_feet 5000
272
+ }
273
+ }
274
+ }
275
+ }
276
+ end
277
+
278
+ it "Conf should respond to merge and merge!" do
279
+ c = SimpleConf {
280
+ a "b"
281
+ }
282
+ [:merge, :merge!].each do |meth|
283
+ c.should respond_to(meth)
284
+ end
285
+ end
286
+
287
+ it "should not accept anything other than another SimpleConf::Conf object" do
288
+ c = SimpleConf {
289
+ server "localhost"
290
+ }
291
+ lambda {
292
+ c.merge!(5)
293
+ }.should raise_error
294
+ end
295
+
296
+ it "should merge! a SimpleConf::Conf" do
297
+
298
+ ret_val = @default.merge!(@new)
299
+
300
+ ret_val.should be_nil
301
+ @default.should be_an_instance_of(SimpleConf::Conf)
302
+
303
+ @default.server.should == "localhost"
304
+ @default.port.should == 90
305
+ @default.socket.should == "haha"
306
+ @default.tree.bugs.should == true
307
+ @default.tree.leafs.should == 60
308
+ @default.tree.height.should == 50
309
+ @default.tree.ants.big.should == false
310
+ @default.tree.ants.home.sq_feet.should == 5000
311
+ end
312
+
313
+ it "should merge a SimpleConf::Conf" do
314
+
315
+ new_conf = @default.merge(@new)
316
+
317
+ new_conf.should be_an_instance_of(SimpleConf::Conf)
318
+ new_conf.should_not eq(@default)
319
+
320
+ new_conf.server.should == "localhost"
321
+ new_conf.port.should == 90
322
+ new_conf.socket.should == "haha"
323
+ new_conf.tree.bugs.should == true
324
+ new_conf.tree.leafs.should == 60
325
+ new_conf.tree.height.should == 50
326
+ new_conf.tree.ants.big.should == false
327
+ new_conf.tree.ants.home.sq_feet.should == 5000
328
+ end
329
+
330
+ it "should merge a SimpleConf::Conf and leave the old one intact" do
331
+ new_conf = @default.merge(@new)
332
+
333
+ @default.server.should == "localhost"
334
+ @default.port == 80
335
+ @default.tree.leafs == 30
336
+ @default.tree.height == 50
337
+ @default.tree.ants.big == false
338
+ @default.tree.ants.fast == true
339
+ @default.tree.ants.home.should be_nil
340
+ lambda { @default.tree.ants.home.sq_feet }.should raise_error
341
+ end
342
+
343
+ context "Properties" do
344
+ before do
345
+ @default = SimpleConf {
346
+ server "localhost"
347
+ port 80, :override => false
348
+ socket "/tmp/sock.sock"
349
+
350
+ tree {
351
+ leafs 30
352
+ height 50
353
+ bugs false, :override => false
354
+ ants{
355
+ big false, :override => false
356
+ fast true
357
+ }
358
+ }
359
+ }
360
+
361
+ end
362
+ it "should merge and inherit options" do
363
+ @default.merge!(@new)
364
+ @default.port 8080
365
+ @default.port.should == 80
366
+ end
367
+
368
+ it "should merge and inherit nested properties" do
369
+ @default.merge!(@new)
370
+ @default.tree.bugs.should == false
371
+ @default.tree.ants.big.should == false
372
+ @default.tree.leafs 200
373
+ @default.tree.leafs.should == 60
374
+ end
375
+ end
376
+
377
+ context "merging with init_only" do
378
+ before do
379
+ @new = SimpleConf(:init_only => true) {
380
+ port 90
381
+ socket "haha"
382
+ tree {
383
+ leafs 60, :override => false
384
+ bugs true
385
+ ants {
386
+ fast false
387
+ home {
388
+ big true
389
+ sq_feet 5000
390
+ }
391
+ }
392
+ }
393
+ }
394
+
395
+ end
396
+
397
+ it "the newly merged item should be init_only" do
398
+ @default.merge!(@new)
399
+ @default.__init_only__.should == true
400
+ end
401
+
402
+ it "the newly merged item should act as init_only" do
403
+ @default.merge!(@new)
404
+ lambda{
405
+ @default.name "name"
406
+ }.should raise_error
407
+ end
408
+ end
409
+
410
+ end
411
+ end
@@ -0,0 +1,2 @@
1
+ $:.unshift File.dirname(__FILE__) + '/../lib'
2
+ require 'simpleconf'
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: simpleconf
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Mike Lewis
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-07-25 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: &2153376680 !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: *2153376680
25
+ - !ruby/object:Gem::Dependency
26
+ name: rspec
27
+ requirement: &2153376260 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *2153376260
36
+ - !ruby/object:Gem::Dependency
37
+ name: blankslate
38
+ requirement: &2153375840 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *2153375840
47
+ description: Simple Configuration DSL that supports merging, locking and more.
48
+ email:
49
+ - ft.mikelewis@gmail.com
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - .gitignore
55
+ - .rspec
56
+ - Gemfile
57
+ - README.md
58
+ - Rakefile
59
+ - lib/core/hash.rb
60
+ - lib/core/kernel.rb
61
+ - lib/simpleconf.rb
62
+ - lib/simpleconf/conf.rb
63
+ - lib/simpleconf/version.rb
64
+ - simpleconf.gemspec
65
+ - spec/simpleconf_spec.rb
66
+ - spec/spec_helper.rb
67
+ homepage: http://github.com/mikelewis/simpleconf
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: simpleconf
87
+ rubygems_version: 1.7.1
88
+ signing_key:
89
+ specification_version: 3
90
+ summary: Simple Configuration DSL that supports merging, locking and more.
91
+ test_files:
92
+ - spec/simpleconf_spec.rb
93
+ - spec/spec_helper.rb