confo-config 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/confo.gemspec +16 -15
- data/lib/confo.rb +2 -2
- data/lib/confo/collection.rb +46 -10
- data/lib/confo/concerns/options_manager.rb +29 -24
- data/lib/confo/concerns/subconfigs_manager.rb +4 -2
- data/lib/confo/config.rb +50 -12
- data/lib/confo/version.rb +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 710b4899fb2c7ff8bb1fe82afdb2ecc5dae2e3ed
|
4
|
+
data.tar.gz: 85ee34a5653d81be7fa89834d770e4778081581e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9415241fcf386be99983cfa849bc4e1ef8549fddae646e560262c78bcaf3d643cf6b49abaf8a6abd2188cf52a0e8e828bdb15e3861da04f3ac4b5138f0fa9920
|
7
|
+
data.tar.gz: 37e68f2e2893d3503b5bfc0d380bdbda569b4199ead0a783c0c1b07eded895de10f9d1a879a3cc2c323f5ef615c97ffea6a8cbb7c501946defcee2295939d4b2
|
data/confo.gemspec
CHANGED
@@ -1,19 +1,20 @@
|
|
1
|
+
# encoding: utf-8
|
1
2
|
require File.expand_path('../lib/confo/version', __FILE__)
|
2
3
|
|
3
|
-
Gem::Specification.new do |
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = 'confo-config'
|
6
|
+
s.version = Confo::VERSION
|
7
|
+
s.authors = ['Yaroslav Konoplov']
|
8
|
+
s.email = ['yaroslav@inbox.com']
|
9
|
+
s.summary = 'Little configuration framework'
|
10
|
+
s.description = 'Little configuration framework'
|
11
|
+
s.homepage = 'http://github.com/yivo/confo-config'
|
12
|
+
s.license = 'MIT'
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
s.executables = `git ls-files -z -- bin/*`.split("\x0").map{ |f| File.basename(f) }
|
15
|
+
s.files = `git ls-files -z`.split("\x0")
|
16
|
+
s.test_files = `git ls-files -z -- {test,spec,features}/*`.split("\x0")
|
17
|
+
s.require_paths = ['lib']
|
17
18
|
|
18
|
-
|
19
|
-
end
|
19
|
+
s.add_dependency 'activesupport', '>= 3.2.0'
|
20
|
+
end
|
data/lib/confo.rb
CHANGED
@@ -22,12 +22,12 @@ module Confo
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def convert_to_hash(value)
|
25
|
-
if value.
|
25
|
+
if value.respond_to?(:to_hash)
|
26
26
|
value.to_hash
|
27
27
|
elsif value.is_a?(Array)
|
28
28
|
value.map { |e| convert_to_hash(e) }
|
29
29
|
else
|
30
|
-
value
|
30
|
+
value
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
data/lib/confo/collection.rb
CHANGED
@@ -2,10 +2,10 @@ module Confo
|
|
2
2
|
class Collection
|
3
3
|
include Enumerable
|
4
4
|
|
5
|
-
attr_reader :
|
5
|
+
attr_reader :settings
|
6
6
|
|
7
|
-
def initialize(
|
8
|
-
@
|
7
|
+
def initialize(settings = {}, &block)
|
8
|
+
@settings = settings
|
9
9
|
configure(&block) if block
|
10
10
|
end
|
11
11
|
|
@@ -14,19 +14,22 @@ module Confo
|
|
14
14
|
config = storage[id]
|
15
15
|
config ||= begin
|
16
16
|
config_class = Confo.call(self, :config_class, id, construct_options)
|
17
|
+
check_config_class!(config_class)
|
17
18
|
config = Confo.call(self, :construct_config, config_class, id, construct_options)
|
18
19
|
storage[id] = config
|
19
20
|
config.set(:name, id)
|
20
21
|
config
|
21
22
|
end
|
22
23
|
|
23
|
-
config.set(options) if options
|
24
|
+
config.set(options) if options && config.kind_of?(Config)
|
24
25
|
config.configure(&block) if block
|
25
26
|
config
|
26
27
|
end
|
27
28
|
|
28
29
|
def get(id)
|
30
|
+
id = convert_id(id)
|
29
31
|
define(id)
|
32
|
+
storage[id]
|
30
33
|
end
|
31
34
|
|
32
35
|
def set(id, config)
|
@@ -49,23 +52,52 @@ module Confo
|
|
49
52
|
end
|
50
53
|
|
51
54
|
def to_a
|
52
|
-
storage.
|
55
|
+
storage.each_with_object([]) do |(id, instance), memo|
|
56
|
+
memo << (instance.respond_to?(:to_hash) ? instance.to_hash : instance)
|
57
|
+
end
|
53
58
|
end
|
54
59
|
|
55
60
|
def to_hash
|
56
|
-
storage.
|
61
|
+
storage.each_with_object({}) do |(id, instance), memo|
|
57
62
|
memo[id] = Confo.convert_to_hash(instance)
|
58
|
-
memo
|
59
63
|
end
|
60
64
|
end
|
61
65
|
|
62
|
-
|
66
|
+
def method_missing(name, *args, &block)
|
67
|
+
if args.empty? && name =~ /^(\w+)\?$/
|
68
|
+
exists?($1)
|
69
|
+
else
|
70
|
+
super
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def with_new_settings(new_settings)
|
75
|
+
self.class.new(settings.merge(new_settings)).tap do |new_obj|
|
76
|
+
if storage = @storage
|
77
|
+
storage.each { |k, v| new_obj.set(k, v.with_new_settings(new_settings) ) }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def dup(config_settings = {})
|
83
|
+
self.class.new(settings.merge(config_settings)).tap do |new_obj|
|
84
|
+
if storage = @storage
|
85
|
+
new_obj.instance_variable_set(:@storage, storage)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def deep_dup(config_settings = {})
|
91
|
+
with_new_settings(config_settings)
|
92
|
+
end
|
93
|
+
|
94
|
+
protected
|
63
95
|
|
64
96
|
def config_class(config_id, config_options)
|
65
97
|
config_options.try(:[], :class_name).try(:safe_constantize) || Config
|
66
98
|
end
|
67
99
|
|
68
|
-
def construct_config(config_class)
|
100
|
+
def construct_config(config_class, config_id, construct_options)
|
69
101
|
config_class.new
|
70
102
|
end
|
71
103
|
|
@@ -74,7 +106,11 @@ module Confo
|
|
74
106
|
end
|
75
107
|
|
76
108
|
def convert_id(id)
|
77
|
-
id.to_sym
|
109
|
+
id.kind_of?(Symbol) ? id : id.to_sym
|
110
|
+
end
|
111
|
+
|
112
|
+
def check_config_class!(config_class)
|
113
|
+
raise 'Forbidden config class!' unless (config_class <= Config or config_class <= Collection)
|
78
114
|
end
|
79
115
|
end
|
80
116
|
end
|
@@ -6,12 +6,20 @@ module Confo
|
|
6
6
|
|
7
7
|
# Define option accessors.
|
8
8
|
def option_accessor(*names)
|
9
|
+
|
10
|
+
# TODO Save list of option names
|
9
11
|
names.each do |name|
|
10
12
|
define_option_functional_accessor(name)
|
11
13
|
define_option_writer(name)
|
12
14
|
end
|
13
15
|
end
|
14
16
|
|
17
|
+
# TODO Implement
|
18
|
+
def readonly_option(*names)
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
protected
|
15
23
|
def define_option_functional_accessor(name)
|
16
24
|
define_method("#{name}") do |*args|
|
17
25
|
if args.size > 0
|
@@ -47,12 +55,13 @@ module Confo
|
|
47
55
|
# Alias for +get+.
|
48
56
|
alias [] get
|
49
57
|
|
50
|
-
|
58
|
+
protected
|
51
59
|
|
52
60
|
# Method to get an option.
|
53
61
|
# If there is an option accessor defined then it will be used.
|
54
62
|
# In other cases +raw_get+ will be used.
|
55
63
|
def public_get(option)
|
64
|
+
# TODO Prevent subconfigs here
|
56
65
|
respond_to?(option) ? send(option) : raw_get(option)
|
57
66
|
end
|
58
67
|
|
@@ -60,11 +69,11 @@ module Confo
|
|
60
69
|
# If value is callable without arguments
|
61
70
|
# it will be called and result will be returned.
|
62
71
|
def raw_get(option)
|
63
|
-
value =
|
72
|
+
value = options_storage[option]
|
64
73
|
Confo.callable_without_arguments?(value) ? value.call : value
|
65
74
|
end
|
66
75
|
|
67
|
-
|
76
|
+
public
|
68
77
|
|
69
78
|
# Sets option:
|
70
79
|
# obj.set(:option, 'value')
|
@@ -82,22 +91,23 @@ module Confo
|
|
82
91
|
# Alias for +set+.
|
83
92
|
alias []= set
|
84
93
|
|
85
|
-
|
94
|
+
protected
|
86
95
|
|
87
96
|
# Method to set an option.
|
88
97
|
# If there is an option accessor defined then it will be used.
|
89
98
|
# In other cases +raw_set+ will be used.
|
90
99
|
def public_set(option, value)
|
100
|
+
# TODO Prevent subconfigs here
|
91
101
|
method = "#{option}="
|
92
102
|
respond_to?(method) ? send(method, value) : raw_set(option, value)
|
93
103
|
end
|
94
104
|
|
95
105
|
# Internal method to set option.
|
96
106
|
def raw_set(option, value)
|
97
|
-
|
107
|
+
options_storage[option] = value
|
98
108
|
end
|
99
109
|
|
100
|
-
|
110
|
+
public
|
101
111
|
|
102
112
|
# Sets option only if it is not set yet:
|
103
113
|
# obj.set_at_first(:option, 1)
|
@@ -129,7 +139,7 @@ module Confo
|
|
129
139
|
set(arg, rest_args.first) unless set?(arg)
|
130
140
|
true
|
131
141
|
else
|
132
|
-
|
142
|
+
options_storage.has_key?(arg)
|
133
143
|
end
|
134
144
|
end
|
135
145
|
|
@@ -142,43 +152,38 @@ module Confo
|
|
142
152
|
|
143
153
|
# Unsets option.
|
144
154
|
def unset(option)
|
145
|
-
|
155
|
+
options_storage.delete(option)
|
146
156
|
self
|
147
157
|
end
|
148
158
|
|
149
159
|
# Returns option names as array of symbols.
|
150
160
|
def keys
|
151
|
-
|
161
|
+
options_storage.each_with_object([]) do |(k, v), memo|
|
152
162
|
memo << k.to_sym
|
153
|
-
memo
|
154
163
|
end
|
155
164
|
end
|
156
165
|
|
157
166
|
# Returns option values as array.
|
158
167
|
def values
|
159
|
-
|
168
|
+
options_storage.each_with_object([]) do |(k, v), memo|
|
169
|
+
memo << get(k)
|
170
|
+
end
|
160
171
|
end
|
161
172
|
|
162
173
|
# Returns all options at once.
|
163
174
|
# obj.options => { option: 'value' }
|
164
175
|
def options
|
165
|
-
|
166
|
-
|
167
|
-
|
176
|
+
options_storage.each_with_object({}) do |(k, v), memo|
|
177
|
+
memo[k.to_sym] = get(k)
|
178
|
+
end
|
168
179
|
end
|
169
180
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
@storage ||= OptionsStorage.new
|
181
|
+
protected
|
182
|
+
def options_storage
|
183
|
+
@options_storage ||= OptionsStorage.new
|
174
184
|
end
|
175
185
|
end
|
176
186
|
|
177
|
-
class OptionsStorage <
|
178
|
-
def to_hash
|
179
|
-
new_hash = {}
|
180
|
-
each { |k, v| new_hash[k.kind_of?(String) ? k.to_sym : k] = Confo.convert_to_hash(v) }
|
181
|
-
Hash.new(default).merge!(new_hash)
|
182
|
-
end
|
187
|
+
class OptionsStorage < ActiveSupport::HashWithIndifferentAccess
|
183
188
|
end
|
184
189
|
end
|
@@ -59,7 +59,7 @@ module Confo
|
|
59
59
|
subconfig_instances.exists?(subconfig_name)
|
60
60
|
end
|
61
61
|
|
62
|
-
|
62
|
+
protected
|
63
63
|
|
64
64
|
def subconfig_instances
|
65
65
|
@subconfig_instances ||= Collection.new
|
@@ -67,6 +67,8 @@ module Confo
|
|
67
67
|
|
68
68
|
def subconfig_internal(subconfig_name, options = nil, overrides = nil, &block)
|
69
69
|
unless subconfig_exists?(subconfig_name)
|
70
|
+
|
71
|
+
# TODO Bugfix
|
70
72
|
subconfig_options = self.class.subconfigs_options[subconfig_name].try(:dup) || {}
|
71
73
|
subconfig_options.merge!(overrides) if overrides
|
72
74
|
|
@@ -88,7 +90,7 @@ module Confo
|
|
88
90
|
|
89
91
|
def subconfig_class(subconfig_name, subconfig_options)
|
90
92
|
if class_name = subconfig_options[:class_name]
|
91
|
-
class_name.
|
93
|
+
class_name.camelize
|
92
94
|
else
|
93
95
|
guess_subconfig_class_name(subconfig_name)
|
94
96
|
end.safe_constantize || subconfig_options.fetch(:fallback_class_name, 'Confo::Config').constantize
|
data/lib/confo/config.rb
CHANGED
@@ -5,14 +5,42 @@ module Confo
|
|
5
5
|
include OptionsManager
|
6
6
|
include SubconfigsManager
|
7
7
|
|
8
|
-
attr_reader :
|
8
|
+
attr_reader :settings
|
9
9
|
|
10
|
-
def initialize(
|
11
|
-
@
|
10
|
+
def initialize(settings = {}, &block)
|
11
|
+
@settings = settings
|
12
12
|
preconfigure
|
13
13
|
configure(&block) if block
|
14
14
|
end
|
15
15
|
|
16
|
+
def with_new_settings(new_settings)
|
17
|
+
self.class.new(settings.merge(new_settings)).tap do |new_config|
|
18
|
+
if var = @options_storage
|
19
|
+
new_config.instance_variable_set(:@options_storage, var.deep_dup)
|
20
|
+
end
|
21
|
+
|
22
|
+
if var = @subconfig_instances
|
23
|
+
new_config.instance_variable_set(:@subconfig_instances, var.with_new_settings(new_settings))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def dup(config_settings = {})
|
29
|
+
self.class.new(settings.merge(config_settings)).tap do |new_config|
|
30
|
+
if var = @options_storage
|
31
|
+
new_config.instance_variable_set(:@options_storage, var)
|
32
|
+
end
|
33
|
+
|
34
|
+
if var = @subconfig_instances
|
35
|
+
new_config.instance_variable_set(:@subconfig_instances, var)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def deep_dup(config_settings = {})
|
41
|
+
with_new_settings(config_settings)
|
42
|
+
end
|
43
|
+
|
16
44
|
def configure(*args, &block)
|
17
45
|
case args.size
|
18
46
|
|
@@ -58,39 +86,49 @@ module Confo
|
|
58
86
|
# Wants to configure subconfig:
|
59
87
|
# object.description { }
|
60
88
|
subconfig(name, &block)
|
61
|
-
else
|
62
89
|
|
90
|
+
# Wants to access boolean option:
|
91
|
+
# object.property?
|
92
|
+
elsif name =~ /^(\w+)\?$/
|
93
|
+
!!get($1)
|
94
|
+
|
95
|
+
else
|
63
96
|
# Wants one of the following:
|
64
97
|
# - access subconfig
|
65
98
|
# - access option
|
66
|
-
subconfig_exists?(name) ? subconfig(name) : option(
|
99
|
+
subconfig_exists?(name) ? subconfig(name) : option(strip_assignment(name))
|
67
100
|
end
|
68
101
|
|
69
102
|
when 1
|
70
103
|
arg = args.first
|
71
104
|
|
105
|
+
# Wants to test option value:
|
106
|
+
# object.property?(:value) => options[:property] == :value
|
107
|
+
if name =~ /^(\w+)\?$/
|
108
|
+
get($1) == arg
|
109
|
+
|
72
110
|
# Wants to access collection:
|
73
111
|
# object.properties :id { }
|
74
|
-
|
112
|
+
elsif (arg.is_a?(String) || arg.is_a?(Symbol)) && subconfig_exists?(name)
|
75
113
|
subconfig(name.to_s.pluralize, arg, &block)
|
76
|
-
else
|
77
114
|
|
115
|
+
else
|
78
116
|
# Wants to access option:
|
79
117
|
# object.cache = :none
|
80
118
|
# object.cache :none
|
81
|
-
option(
|
119
|
+
option(strip_assignment(name), arg)
|
82
120
|
end
|
83
121
|
|
84
122
|
else
|
85
|
-
option(
|
123
|
+
option(strip_assignment(name), *args)
|
86
124
|
end
|
87
125
|
end
|
88
126
|
|
89
127
|
def to_hash
|
90
|
-
|
128
|
+
options.merge!(subconfigs).to_hash
|
91
129
|
end
|
92
130
|
|
93
|
-
|
131
|
+
protected
|
94
132
|
|
95
133
|
def preconfigure
|
96
134
|
preconfigurator_class = lookup_preconfigurator_class
|
@@ -114,7 +152,7 @@ module Confo
|
|
114
152
|
"#{configurable_component_name}Preconfigurator"
|
115
153
|
end
|
116
154
|
|
117
|
-
def
|
155
|
+
def strip_assignment(name)
|
118
156
|
name.to_s.sub(/=+\Z/, '').to_sym
|
119
157
|
end
|
120
158
|
end
|
data/lib/confo/version.rb
CHANGED
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: confo-config
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yaroslav Konoplov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-12-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 3.2.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 3.2.0
|
27
27
|
description: Little configuration framework
|
28
28
|
email:
|
29
29
|
- yaroslav@inbox.com
|