confo-config 1.0.0 → 1.0.1
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.
- 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
|