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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e18009a32d37da15b10c87cff286b37be9ff6a2e
4
- data.tar.gz: 0e2ad064b148ef7237ec98722afebb703dd8b2bb
3
+ metadata.gz: 710b4899fb2c7ff8bb1fe82afdb2ecc5dae2e3ed
4
+ data.tar.gz: 85ee34a5653d81be7fa89834d770e4778081581e
5
5
  SHA512:
6
- metadata.gz: f759fb4b9277b5f78c559cda2e270d97d2741827f2536e3cb40578d97f902eda3eaceac0906bcef6cc0b898fda0fdf1f0f105712d5fcd1570342d67eb453c548
7
- data.tar.gz: d05dbef7d09242b374b5872202349dd315c7899302554e08dd143db3c30b55a5f26f7446d50e588df09bf43aebb69be38425ac63648a44debfec0f8e7cc475ae
6
+ metadata.gz: 9415241fcf386be99983cfa849bc4e1ef8549fddae646e560262c78bcaf3d643cf6b49abaf8a6abd2188cf52a0e8e828bdb15e3861da04f3ac4b5138f0fa9920
7
+ data.tar.gz: 37e68f2e2893d3503b5bfc0d380bdbda569b4199ead0a783c0c1b07eded895de10f9d1a879a3cc2c323f5ef615c97ffea6a8cbb7c501946defcee2295939d4b2
@@ -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 |spec|
4
- spec.name = 'confo-config'
5
- spec.version = Confo::VERSION
6
- spec.authors = ['Yaroslav Konoplov']
7
- spec.email = ['yaroslav@inbox.com']
8
- spec.summary = 'Little configuration framework'
9
- spec.description = 'Little configuration framework'
10
- spec.homepage = 'http://github.com/yivo/confo-config'
11
- spec.license = 'MIT'
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
- spec.files = `git ls-files -z`.split("\x0")
14
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
15
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
16
- spec.require_paths = ['lib']
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
- spec.add_dependency 'activesupport', '~> 4.0' # 4.0 <= version < 5.0
19
- end
19
+ s.add_dependency 'activesupport', '>= 3.2.0'
20
+ end
@@ -22,12 +22,12 @@ module Confo
22
22
  end
23
23
 
24
24
  def convert_to_hash(value)
25
- if value.is_a?(Hash)
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.respond_to?(:to_hash) ? value.to_hash : value
30
+ value
31
31
  end
32
32
  end
33
33
 
@@ -2,10 +2,10 @@ module Confo
2
2
  class Collection
3
3
  include Enumerable
4
4
 
5
- attr_reader :behaviour_options
5
+ attr_reader :settings
6
6
 
7
- def initialize(behaviour_options = {}, &block)
8
- @behaviour_options = behaviour_options
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.values
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.reduce({}) do |memo, (id, instance)|
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
- protected
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
- protected
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 = storage[option]
72
+ value = options_storage[option]
64
73
  Confo.callable_without_arguments?(value) ? value.call : value
65
74
  end
66
75
 
67
- public
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
- protected
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
- storage[option] = value
107
+ options_storage[option] = value
98
108
  end
99
109
 
100
- public
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
- storage.has_key?(arg)
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
- storage.delete(option)
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
- storage.reduce([]) do |memo, k, v|
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
- storage.values
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
- options = storage.dup
166
- options.each { |k, v| options[k] = get(k) }
167
- options
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
- protected
171
-
172
- def storage
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 < Hash
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
- protected
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.to_s.camelize
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
@@ -5,14 +5,42 @@ module Confo
5
5
  include OptionsManager
6
6
  include SubconfigsManager
7
7
 
8
- attr_reader :behaviour_options
8
+ attr_reader :settings
9
9
 
10
- def initialize(behaviour_options = {}, &block)
11
- @behaviour_options = behaviour_options
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(normalize_option(name))
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
- if (arg.is_a?(String) || arg.is_a?(Symbol)) && subconfig_exists?(name)
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(normalize_option(name), arg)
119
+ option(strip_assignment(name), arg)
82
120
  end
83
121
 
84
122
  else
85
- option(normalize_option(name), *args)
123
+ option(strip_assignment(name), *args)
86
124
  end
87
125
  end
88
126
 
89
127
  def to_hash
90
- {}.merge!(options.to_hash).merge!(subconfigs.to_hash)
128
+ options.merge!(subconfigs).to_hash
91
129
  end
92
130
 
93
- protected
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 normalize_option(name)
155
+ def strip_assignment(name)
118
156
  name.to_s.sub(/=+\Z/, '').to_sym
119
157
  end
120
158
  end
@@ -1,3 +1,3 @@
1
1
  module Confo
2
- VERSION = '1.0.0'
2
+ VERSION = '1.0.1'
3
3
  end
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.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-09-04 00:00:00.000000000 Z
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: '4.0'
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: '4.0'
26
+ version: 3.2.0
27
27
  description: Little configuration framework
28
28
  email:
29
29
  - yaroslav@inbox.com