funfig 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/Gemfile +4 -0
- data/README +81 -0
- data/Rakefile +1 -0
- data/funfig.gemspec +24 -0
- data/lib/funfig/version.rb +3 -0
- data/lib/funfig.rb +292 -0
- metadata +52 -0
data/Gemfile
ADDED
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
|
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: []
|