funfig 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ *.sw[po]
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in funfig.gemspec
4
+ gemspec
data/README ADDED
@@ -0,0 +1,81 @@
1
+ Example
2
+ =======
3
+
4
+ require 'funfig'
5
+
6
+ UploadConf = Funfig.new do
7
+ p.root '/services'
8
+ g.nginx do
9
+ p.folder { File.join(_.root, 'nginx') }
10
+ p.port '8000'
11
+ end
12
+ p.public_ip_port '*:80'
13
+ end
14
+
15
+ conf = UploadConf.new
16
+ p conf.nginx.folder
17
+ conf.root = "~/MailProject/upload"
18
+ p conf.nginx.folder
19
+ conf.each {|k,v| puts "#{k} #{v}"}
20
+ p conf
21
+ p conf.to_hash()
22
+ p conf.to_hash(true)
23
+
24
+ Up1Conf = UploadConf.clone do
25
+ g.nginx do
26
+ p.folder { File.join(_.root, 'nganx') }
27
+ p.location '/public'
28
+ end
29
+ end
30
+
31
+ conf1 = Up1Conf.new
32
+ conf1.update(conf.to_hash())
33
+ p conf1
34
+ conf1.nginx_reset!
35
+ p conf1
36
+
37
+ TODO
38
+ ====
39
+
40
+ 1. define array of same kinds
41
+
42
+ Conf = Funfig.new do
43
+ p.port 8000
44
+ p.folder '/folder'
45
+ array :servers do
46
+ p.port { _parent.port + _pos }
47
+ p.folder { File.join(_parent.folder, _pos.to_s) }
48
+ end
49
+ a.servers1 do
50
+ p.port { _parent.port + _pos }
51
+ p.folder { File.join(_parent.folder, _pos.to_s) }
52
+ end
53
+ end
54
+
55
+ 2. define hash of same kinds
56
+
57
+ Conf = Funfig.new do
58
+ hash :environments do
59
+ p.host 'localhost'
60
+ p.database { "mybase_#{_name}" }
61
+ end
62
+ h.environments1 do
63
+ p.host 'localhost'
64
+ p.database { "mybase_#{_name}" }
65
+ end
66
+ end
67
+
68
+ 3. Correct composition of schemes
69
+
70
+ ConfServ = Funfig.new do
71
+ p.port 80
72
+ p.ip '192.168.168.192'
73
+ end
74
+
75
+ ConfApp = Funfig.new do
76
+ p.path '/srv/path'
77
+ g.server ConfServ do
78
+ p.path { _.path }
79
+ end
80
+ end
81
+
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/funfig.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "funfig/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "funfig"
7
+ s.version = Funfig::VERSION
8
+ s.authors = ["Sokolov Yura 'funny-falcon'"]
9
+ s.email = ["funny.falcon@gmail.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{Configuration with calculable defaults}
12
+ s.description = %q{Defines configuration schema with calculable defaults}
13
+
14
+ s.rubyforge_project = "funfig"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ # s.add_development_dependency "rspec"
23
+ # s.add_runtime_dependency "rest-client"
24
+ end
@@ -0,0 +1,3 @@
1
+ module Funfig
2
+ VERSION = "0.0.2"
3
+ end
data/lib/funfig.rb ADDED
@@ -0,0 +1,292 @@
1
+ require "funfig/version"
2
+ require "yaml" unless defined? YAML
3
+
4
+ module Funfig
5
+ NOT_SET = Object.new.freeze
6
+ class ProxyParam < BasicObject
7
+ def initialize(group)
8
+ @group = group
9
+ end
10
+ def method_missing(name, value = NOT_SET, &block)
11
+ unless value.equal? NOT_SET
12
+ @group.param name, value
13
+ else
14
+ @group.param name, &block
15
+ end
16
+ end
17
+ end
18
+
19
+ class ProxyGroup < BasicObject
20
+ def initialize(group)
21
+ @group = group
22
+ end
23
+ def method_missing(name, &block)
24
+ @group.group name, &block
25
+ end
26
+ end
27
+
28
+ class Group
29
+ def initialize(parent=nil) # :nodoc:
30
+ @parent = parent
31
+ end
32
+
33
+ # Get enclosing group
34
+ def _parent
35
+ @parent
36
+ end
37
+
38
+ # Get root of configuration
39
+ # :call-seq:
40
+ # _
41
+ # _root
42
+ def _
43
+ @parent._
44
+ end
45
+ alias _root _
46
+
47
+ # Update config by yaml file
48
+ def load_file(filename)
49
+ params = YAML.load_file(filename)
50
+ update(params)
51
+ end
52
+
53
+ # Update config by hash
54
+ def update(hash)
55
+ hash.each{|k, v|
56
+ self.send("#{k}=", v)
57
+ }
58
+ end
59
+
60
+ # Iterate over parameter names
61
+ def each_param
62
+ return to_enum(:each_param) unless block_given?
63
+ self.class._params.each{|k, _|
64
+ yield k
65
+ }
66
+ end
67
+
68
+ # Iterate over parameters and values
69
+ # If called with parameter +true+, then iterate only over explicit setted parameters
70
+ #
71
+ # :call-seq:
72
+ # config.each{|name, value| puts "#{name} = #{value}"}
73
+ # config.each(true){|name, value| puts "#{name} = #{value}"}
74
+ def each(explicit=false)
75
+ return to_enum(:each, explicit) unless block_given?
76
+ self.class._params.each{|k, _|
77
+ yield k, send(k) unless explicit && !instance_variable_defined?("@#{k}")
78
+ }
79
+ end
80
+
81
+ # Convert configuration to hash
82
+ # If called with parameter +true+ than consider only explicit setted parameters
83
+ def to_hash(explicit=false)
84
+ h = {}
85
+ each(explicit){|k, v|
86
+ if Group === v
87
+ v = v.to_hash(explicit)
88
+ next if explicit && v.empty?
89
+ end
90
+ h[k] = v
91
+ }
92
+ h
93
+ end
94
+
95
+ def inspect
96
+ "<#{self.class.name} #{each.map{|k,v| "#{k}=#{v.inspect}"}.join(' ')}>"
97
+ end
98
+
99
+ # :stopdoc:
100
+
101
+ def _cache_get(k, &block)
102
+ _._cache.fetch(_sub_name(k), NOT_SET)
103
+ end
104
+
105
+ def _cache_set(k, v)
106
+ _._cache[_sub_name(k)] = v
107
+ end
108
+
109
+ def _sub_name(name)
110
+ self.class._sub_name(name)
111
+ end
112
+
113
+ def _path
114
+ self.class._path
115
+ end
116
+
117
+ def self._params
118
+ @params ||= {}
119
+ end
120
+
121
+ def self.initialize_clone(arg)
122
+ super
123
+ if @params
124
+ params, @params = @params, {}
125
+ params.each{|name, par|
126
+ if par.is_a?(Class) && Group >= par
127
+ @params[name] = par.clone
128
+ else
129
+ @params[name] = par
130
+ end
131
+ }
132
+ end
133
+ end
134
+
135
+ def self._sub_name(name)
136
+ "#{_path}.#{name}"
137
+ end
138
+
139
+ # :startdoc:
140
+
141
+ # Define named group of values
142
+ #
143
+ # :call-seq:
144
+ # config = Funfig.new do
145
+ # group :name_of_group do
146
+ # end
147
+ # end
148
+ def self.group(name, &block)
149
+ name = name.to_sym
150
+ vname = :"@#{name}"
151
+ _prev = _params[name]
152
+ klass = _prev.is_a?(Class) && Group >= _prev ? _prev : Class.new(Group)
153
+ _params[name] = klass
154
+ path = _sub_name(name)
155
+ const_set name.capitalize, klass
156
+
157
+ klass.send(:define_singleton_method, :_path) do
158
+ path
159
+ end
160
+
161
+ define_method(name) do
162
+ instance_variable_get(vname) ||
163
+ instance_variable_set(vname, klass.new(self))
164
+ end
165
+
166
+ define_method("#{name}=") do |hash|
167
+ send(name).update(hash)
168
+ end
169
+
170
+ define_method("#{name}_reset!") do
171
+ _._cache_clear!
172
+ remove_instance_variable(vname) if instance_variable_defined?(vname)
173
+ end
174
+ klass.class_exec ProxyParam.new(klass), &block
175
+ end
176
+
177
+ # define named parameter
178
+ #
179
+ # :call-seq:
180
+ # config = Funfig.new do
181
+ # param :name_of_param do calculate_default_value end
182
+ # end
183
+ def self.param(name, value = NOT_SET, &block)
184
+ _params[name] = true
185
+ vname = :"@#{name}"
186
+ name = name.to_sym
187
+
188
+ block ||= proc{
189
+ begin
190
+ value.dup
191
+ rescue TypeError
192
+ block = proc { value }
193
+ value
194
+ end
195
+ }
196
+
197
+ define_method(name) do
198
+ if instance_variable_defined?(vname)
199
+ instance_variable_get(vname)
200
+ else
201
+ if (v = _cache_get(name)).equal? NOT_SET
202
+ raise "Parameter #{_sub_name(name)} must be set!" unless block
203
+ _cache_set(name, (v = instance_eval &block))
204
+ end
205
+ v
206
+ end
207
+ end
208
+
209
+ define_method("#{name}=") do |v|
210
+ _._cache_clear!
211
+ instance_variable_set(vname, v)
212
+ end
213
+
214
+ define_method("#{name}_reset!") do
215
+ _._cache_clear!
216
+ remove_instance_variable(vname) if instance_variable_defined?(vname)
217
+ end
218
+ end
219
+
220
+ # syntax sugar proxy for declaring params
221
+ #
222
+ # :call-seq
223
+ # conf = Funfig.new do
224
+ # p.name_of_param :default_value
225
+ # p.other_param { calculate_default }
226
+ # end
227
+ def self.p
228
+ @proxy_param ||= ProxyParam.new(self)
229
+ end
230
+
231
+ # syntax sugar proxy for declaring group
232
+ #
233
+ # :call-seq
234
+ # conf = Funfig.new do
235
+ # g.name_of_group do
236
+ # end
237
+ # end
238
+ def self.g
239
+ @group_param ||= ProxyGroup.new(self)
240
+ end
241
+
242
+ # Create a copy of configuration scheme
243
+ #
244
+ # :call-seq:
245
+ # other_conf = config.clone do
246
+ # param :other_value do other_default end
247
+ # end
248
+ def self.clone(&block)
249
+ new = super
250
+ new.send(:class_eval, &block) if block_given?
251
+ new
252
+ end
253
+ end
254
+
255
+ # :stopdoc:
256
+ class Root < Group
257
+ attr_reader :_cache
258
+ def initialize
259
+ @_cache = {}
260
+ end
261
+
262
+ def _cache_clear!
263
+ @_cache.clear
264
+ end
265
+
266
+ def _parent
267
+ raise "Already at root"
268
+ end
269
+
270
+ def _
271
+ self
272
+ end
273
+
274
+ def self._path
275
+ ""
276
+ end
277
+
278
+ def self._sub_name(name)
279
+ name.to_s
280
+ end
281
+ end
282
+ # :startdoc:
283
+
284
+ # Create configuration schema
285
+ #
286
+ # :call-seq:
287
+ def self.new(&block)
288
+ conf = Class.new(Root)
289
+ conf.class_exec ProxyParam.new(conf), &block
290
+ conf
291
+ end
292
+ end
metadata ADDED
@@ -0,0 +1,52 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: funfig
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Sokolov Yura 'funny-falcon'
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-03-30 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Defines configuration schema with calculable defaults
15
+ email:
16
+ - funny.falcon@gmail.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - .gitignore
22
+ - Gemfile
23
+ - README
24
+ - Rakefile
25
+ - funfig.gemspec
26
+ - lib/funfig.rb
27
+ - lib/funfig/version.rb
28
+ homepage: ''
29
+ licenses: []
30
+ post_install_message:
31
+ rdoc_options: []
32
+ require_paths:
33
+ - lib
34
+ required_ruby_version: !ruby/object:Gem::Requirement
35
+ none: false
36
+ requirements:
37
+ - - ! '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ required_rubygems_version: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ requirements: []
47
+ rubyforge_project: funfig
48
+ rubygems_version: 1.8.17
49
+ signing_key:
50
+ specification_version: 3
51
+ summary: Configuration with calculable defaults
52
+ test_files: []