funfig 0.0.2

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,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: []