configurates 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0e9942377c030d89736ff37299d6ba12de638b48
4
+ data.tar.gz: 6a9f55676dbe4c957633bd664dcaea9df6bdcd3e
5
+ SHA512:
6
+ metadata.gz: dcb4745cdfff415407998781a4bcf762a0914f5576cd47057b80a66df178ba7a78e83476c42f6737bdea6b5ad0403e81461f97a633f2a6992358319ae2c34aba
7
+ data.tar.gz: 0b2ee8cab588f48fc993e17e424c41542a963c9e181cb137b49579489e7fdd398ca7384dceb6249444b26396987b485101f93b0626a7543df0eba89b934e1e4c
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'rspec', '~> 3.5.0'
7
+ gem 'pry', '~> 0.10.4'
8
+ gem 'rubocop', '~> 0.42.0'
9
+ end
10
+
11
+ group :test do
12
+ gem 'rake', '~> 11.2.2'
13
+ end
data/LICENSE ADDED
@@ -0,0 +1,9 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) <2016> Medvedu
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new
6
+
7
+ task :default => :spec
@@ -0,0 +1,101 @@
1
+ # encoding: utf-8
2
+
3
+ require 'yaml'
4
+
5
+ require File.join(__dir__, 'configurates', 'provider')
6
+ require File.join(__dir__, 'configurates', 'provider', 'yaml')
7
+ require File.join(__dir__, 'configurates', 'provider', 'environment')
8
+ require File.join(__dir__, 'configurates', 'storage')
9
+
10
+ #
11
+ # Settings::Config is a module that provides agile way to work with
12
+ # configuration, which can be useful for object initialization with default
13
+ # settings. See details below:
14
+ #
15
+ # class MyClass
16
+ #
17
+ # def initialize
18
+ # config = Settings::Config.create do
19
+ # merge_storage( Settings::Yaml.load('path/to/my/yaml/file'),
20
+ # root: 'myclass/default' )
21
+ # end
22
+ #
23
+ # if config.download?
24
+ # @power = config.power
25
+ # @value = config.actual.value
26
+ # else
27
+ # print config['WARNING_MESSAGE']
28
+ # end
29
+ # end
30
+ # end
31
+ #
32
+ # This code demonstrates next concepts:
33
+ #
34
+ # First. You can choose what config part should be loaded. It can be useful for
35
+ # small projects where you do not want to create more than one config file. It
36
+ # means even if whole config placed in one place it is possible to load small
37
+ # data/file part.
38
+ #
39
+ # Second. You can select an object from where configs can be loaded. By default
40
+ # it can be Settings::Yaml or Settings::ENV provider
41
+ #
42
+ # Third. Chains are allowed.
43
+ #
44
+ #
45
+ module Settings
46
+ #
47
+ #
48
+ #
49
+ class Config
50
+ attr_reader :root
51
+
52
+ include Provider
53
+
54
+ #
55
+ # Currently provider(s) can be registered only when we creating new instance
56
+ # based on Settings:Config class. It means self.create should be a higher
57
+ # function.
58
+ #
59
+ def self.create(&callback)
60
+ msg = 'Provider not being chosen'
61
+ raise NoBlockGiven, msg unless block_given?
62
+ new(&callback)
63
+ end
64
+
65
+ private
66
+
67
+ #
68
+ # Run &callback code in object instance.
69
+ #
70
+ def initialize(&callback)
71
+ instance_eval(&callback)
72
+ end
73
+
74
+ #
75
+ # Provide message redirect in the @root (storage) if it's possible.
76
+ #
77
+ def method_missing(msg, *args, &blk)
78
+ message_for_root?(msg) ? @root.send(msg, *args, &blk) : super
79
+ end
80
+
81
+ #
82
+ # And extend respond_to with storate's responses
83
+ #
84
+ def respond_to?(msg, include_private = false)
85
+ super || message_for_root?(msg) ? true : false
86
+ end
87
+
88
+ #
89
+ #
90
+ #
91
+ def message_for_root?(msg)
92
+ @root.send(:respond_to?, msg) ? true : false
93
+ end
94
+
95
+ #
96
+ # This is supposed to be raised when we trying to create instance for
97
+ # Settings::Config class without &codeblock
98
+ #
99
+ class NoBlockGiven < StandardError; end
100
+ end # class Settings::Config
101
+ end # module Settings
@@ -0,0 +1,89 @@
1
+ # encoding: utf-8
2
+
3
+ module Settings
4
+ #
5
+ # Module Provider is an inclusion for Settings::Config class.
6
+ #
7
+ # This module used for provider validations and data normalization.
8
+ #
9
+ # Details:
10
+ #
11
+ # Any provider (f.e. Settings::Yaml should respond to :data and :load
12
+ # methods, otherwise an exception will be raised.
13
+ #
14
+ # Any provider after provider.data method call should return non-empty hash,
15
+ # otherwise an exception will be raised.
16
+ #
17
+ # Provider should present non-empty sub-hash if optional parameter "#{root}"
18
+ # was used. For example for root: 'data/day1', original hash needs to include
19
+ # subhash like:
20
+ #
21
+ # hash = {…, …, data: {…, day1: { …, … }, … }, … }
22
+ #
23
+ module Provider
24
+ private
25
+
26
+ #
27
+ # Can be called only when Settings::Config class is initializing.
28
+ #
29
+ def merge_storage(provider, root: nil)
30
+ msg = "Provider #{provider} does not respond on :data or :load messages"
31
+ raise ProviderNotRespond, msg unless provider.class.respond_to?(:load) &&
32
+ provider.respond_to?(:data)
33
+
34
+ hsh = validate_and_extract_hash_from(provider)
35
+ extract_sub_hash_from(hsh, root)
36
+ defined?(@root) ? @root.merge(hsh) : @root = Storage.create(hsh)
37
+ end
38
+
39
+ #
40
+ # mutate hash unless root parameter is nil. Raise an exception if
41
+ # mutation result is not a valid hash.
42
+ #
43
+ def extract_sub_hash_from(hsh, root)
44
+ return hsh if root.nil?
45
+ tmp = hsh
46
+ root.split('/').each do |path|
47
+ tmp = tmp[path.to_sym]
48
+ msg = "No sub hash with symbol name '#{path}' for #{hsh} was found!"
49
+ raise RootNotExist, msg unless hash_valid?(tmp)
50
+ end
51
+ hsh.replace tmp
52
+ end
53
+
54
+ #
55
+ # encapsulate & extract & validate hash from provider
56
+ #
57
+ def validate_and_extract_hash_from(provider)
58
+ hsh = provider.data.dup
59
+ msg = "#{hsh} is not valid or empty Hash!"
60
+ raise HashNotValid, msg unless hash_valid?(hsh)
61
+ hsh
62
+ end
63
+
64
+ #
65
+ # valid hash is a non-empty hash object
66
+ #
67
+ def hash_valid?(hsh)
68
+ hsh.is_a?(Hash) && !hsh.empty? ? true : false
69
+ end
70
+
71
+ #
72
+ # This is supposed to be raised when provider not respond to :data
73
+ # or :load messages
74
+ #
75
+ class ProviderNotRespond < StandardError; end
76
+
77
+ #
78
+ # This is supposed to be raised when hash is not really a Hash or just
79
+ # when it is empty.
80
+ #
81
+ class HashNotValid < StandardError; end
82
+
83
+ #
84
+ # This is supposed to be raised when we cant extract a valid sub-hash
85
+ # from hash. In other words Root for hash not exist.
86
+ #
87
+ class RootNotExist < StandardError; end
88
+ end # module Settings::Provider
89
+ end # module Settings
@@ -0,0 +1,34 @@
1
+ # encoding: utf-8
2
+
3
+ module Settings
4
+ #
5
+ #
6
+ #
7
+ class ENV
8
+ #
9
+ #
10
+ #
11
+ def self.load(hsh)
12
+ new(hsh)
13
+ end
14
+
15
+ #
16
+ #
17
+ #
18
+ attr_reader :data
19
+
20
+ private
21
+
22
+ def initialize(hsh)
23
+ msg = "object #{hsh} should be an instance of Hash!"
24
+ raise HashNotValid, msg unless Hash === hsh
25
+ @data = hsh.dup
26
+ end
27
+
28
+ #
29
+ # This is supposed to be raised when self.load got a wrong object which
30
+ # can't response as a Hash.
31
+ #
32
+ class HashNotValid < StandardError; end
33
+ end # class Settings::YAML
34
+ end # module Settings
@@ -0,0 +1,42 @@
1
+ # encoding: utf-8
2
+
3
+ module Settings
4
+ #
5
+ #
6
+ #
7
+ class Yaml
8
+ #
9
+ #
10
+ #
11
+ def self.load(path = nil)
12
+ path ||= '../configs/default.yml'
13
+ new(path)
14
+ end
15
+
16
+ #
17
+ #
18
+ #
19
+ attr_reader :data
20
+
21
+ private
22
+
23
+ def initialize(path)
24
+ @path = File.absolute_path(path)
25
+ begin
26
+ @data = YAML.load_file(@path)
27
+ rescue Errno::ENOENT
28
+ msg = "file with path: #{@path} not found!"
29
+ raise FileNotFound, msg
30
+ end
31
+ end
32
+
33
+ # file path
34
+ attr_reader :path
35
+
36
+ #
37
+ # This is supposed to be raised when file transerred to the self.load
38
+ # method wasn't found.
39
+ #
40
+ class FileNotFound < StandardError; end
41
+ end # class Settings::YAML
42
+ end # module Settings
@@ -0,0 +1,183 @@
1
+ # encoding: utf-8
2
+
3
+ module Settings
4
+ #
5
+ #
6
+ #
7
+ class Storage
8
+ #
9
+ # Create new storage.
10
+ #
11
+ # Get hash and try to register each key as method or even sub-storage (it
12
+ # needs for nested hashes). Some keys are not allowed for method
13
+ # registration (f.e. when key = :42). All limitation about Ruby methods
14
+ # naming convention. You can get access to method with any name throw []
15
+ # thought.
16
+ #
17
+ # WARNING! Storage is case-sensitive! It means that keys :config and :Config
18
+ # are two different keys!
19
+ #
20
+ # Sample:
21
+ #
22
+ #
23
+ # hsh = { cinema: 'tiger',
24
+ # rate: {3: 'excellent', 2: 'good', 1: 'overage', 0: 'not rated'},
25
+ # watched: false,
26
+ # 'premier' 'soon'
27
+ # }
28
+ #
29
+ #
30
+ # s = Storage.new(hsh)
31
+ #
32
+ # s.cinema # => 'tiger'
33
+ # s.rate[0] # => 'not rated'
34
+ # s.watched? # => false
35
+ # s['premier'] # => soon
36
+ #
37
+ def self.create(hsh)
38
+ new hsh
39
+ end
40
+
41
+ #
42
+ # Alternative way to get stored value.
43
+ #
44
+ # How it can be used:
45
+ #
46
+ # conf[:load][:raise_on_error] # => true
47
+ # conf.load['skip_headers'] # => :yes
48
+ #
49
+ # Method will raise an ValueNotFound exception if nothing was found.
50
+ #
51
+ def [](arg)
52
+ return @storage[arg] unless @storage[arg].nil?
53
+ chaild = find_child_for_response(arg)
54
+ return chaild unless chaild.nil?
55
+ msg = "Variable with name '#{arg}' not found!"
56
+ raise ValueNotFound, msg
57
+ end
58
+
59
+ #
60
+ # NOT IMPLEMENTED!
61
+ #
62
+ def merge(_hsh)
63
+ raise StandardError, 'not implemented!'
64
+ end
65
+
66
+ private
67
+
68
+ #
69
+ # Initialization.
70
+ # Additional param "#{name}" is used only for nested storage naming.
71
+ #
72
+ def initialize(hsh, name = nil)
73
+ set_initial_values name
74
+ fill_in_storage hsh
75
+ end
76
+
77
+ #
78
+ # Slightly better way to tell about storage.
79
+ #
80
+ def to_ary
81
+ [nodes: @childs.map(&:name), variables: @storage.to_h]
82
+ end
83
+
84
+ #
85
+ #
86
+ #
87
+ def set_initial_values(name = nil)
88
+ @name ||= name || 'root'
89
+ @childs ||= []
90
+ @storage ||= {}
91
+ end
92
+
93
+ #
94
+ # For each pair "key: value" in #{"input_hsh"} we need to find a place where
95
+ # pairs can be stored. So, pairs with values === Hash is used to create new
96
+ # storages, other pairs will be stored in current storage.
97
+ #
98
+ def fill_in_storage(input_hsh)
99
+ tmp = input_hsh.dup
100
+ tmp.each_pair do |key, value|
101
+ case value
102
+ when Hash
103
+ @childs << Storage.new(value, key)
104
+ else
105
+ @storage[key] = value
106
+ register_methods_for key if key_can_be_a_method?(key)
107
+ end
108
+ end
109
+ end
110
+
111
+ #
112
+ # Unfortunately some names are not allowed to be registered as methods.
113
+ # With key_can_be_a_method we should determinate is it possible to
114
+ # define a method with "#{key}" name or not.
115
+ #
116
+ def key_can_be_a_method?(key)
117
+ key_as_string_valid_integer = key.to_s.to_i.to_s == key.to_s
118
+ key.is_a?(Integer) || key_as_string_valid_integer ? false : true
119
+ end
120
+
121
+ #
122
+ # Register method with #method_name.
123
+ #
124
+ # For TrueClass or FalseClass === @storage[method_name] it will
125
+ # define additional predicate method, like:
126
+ #
127
+ # config.skip_lazy_load? # => true
128
+ #
129
+ def register_methods_for(method_name)
130
+ define_singleton_method(method_name.to_sym) do
131
+ @storage[method_name]
132
+ end
133
+
134
+ return unless [true, false].include? @storage[method_name]
135
+ define_singleton_method("#{method_name.to_sym}?") do
136
+ @storage[method_name]
137
+ end
138
+ end
139
+
140
+ #
141
+ # Redirect message to childen node if this node can response to the message
142
+ # otherwise try to responce itself
143
+ #
144
+ def method_missing(method, *args, &blk)
145
+ child = find_child_for_response(method)
146
+ child.nil? ? super : child
147
+ end
148
+
149
+ #
150
+ # Return TRUE if storage or any childen node can response to the message
151
+ # otherwise return FALSE
152
+ #
153
+ def respond_to?(method, include_private = false)
154
+ super || find_child_for_response(method) ? true : false
155
+ end
156
+
157
+ #
158
+ # Look for nested node with the "#{name}". Since we working with hash we
159
+ # can believe that only one nested storage can be found (equal names
160
+ # disallowed).
161
+ #
162
+ def find_child_for_response(name)
163
+ @childs.select { |chaild| chaild.name == name }.first
164
+ end
165
+
166
+ protected
167
+
168
+ # Name for node. Root node has 'root' name.
169
+ attr_reader :name
170
+
171
+ # Subnodes array (childs) for current node. Can be empty.
172
+ attr_reader :childs
173
+
174
+ # Values array (storage) for methods registered in the node.
175
+ attr_reader :storage
176
+
177
+ #
178
+ # This is supposed to be raised when we didn't found assigned
179
+ # method for value in storage.
180
+ #
181
+ class ValueNotFound < StandardError; end
182
+ end # class Settings::Storage
183
+ end # module Settings
data/readme.md ADDED
@@ -0,0 +1,98 @@
1
+ # configurates
2
+
3
+ ## DESCRIPTION
4
+
5
+ customizable_configuration is a lib that provides agile way to work with configuration, which can be useful for object initialization.
6
+
7
+ ## Travis CI
8
+
9
+ https://travis-ci.org/Medvedu/customizable_configuration
10
+
11
+ ## SAMPLES
12
+
13
+ ### SAMPLE 1. BASICS
14
+
15
+ ```ruby
16
+ conf = Settings::Config.create do
17
+ merge_storage Settings::Yaml.load('../configs/first.yml')
18
+ end
19
+
20
+ # Two ways to get an attribute:
21
+ puts conf['string'] # => 4
22
+ puts conf.string # => 4
23
+
24
+ # Any marchalized class is a valid data:
25
+ puts conf.sample.dd.to_s # => 2016-09-05 05:42:35 +0300
26
+
27
+ # Nested hash determitated as sub-storage
28
+ puts conf.sample # => {:nodes=>[:cc],
29
+ # :variables=>{:aa=>15,
30
+ # :bb=>[false, true],
31
+ # :dd=>2016-09-05 05:42:35 +0300} }
32
+
33
+ # Access by [] to predicate
34
+ puts conf[42].root? # => false
35
+ ```
36
+
37
+ ### SAMPLE 2. Tricks
38
+
39
+ ```ruby
40
+ ## PART 1 CASE-SENSIVITY
41
+
42
+ # Warning! Keys are case-sensivity. It means that 'config' and 'Config' are
43
+ # two different keys
44
+
45
+ yaml = Settings::Config.create do
46
+ merge_storage Settings::Yaml.load('../configs/second.yml')
47
+ end
48
+
49
+ puts yaml.config # => {:nodes=>[], :variables=>{:param1=>"config/param1",
50
+ # :param2=>false, :param3=>[]}}
51
+
52
+ puts yaml.Config # => {:nodes=>[:param3], :variables=>{:param1=>"Config/param1",
53
+ # :param2=>[true]}}
54
+
55
+ ## PART 2 ROOT
56
+
57
+ # Sometimes can be useful to load only a part of hash from file, so you can
58
+ # use root parameter for merge_storage method:
59
+
60
+ file = Settings::Yaml.load('../configs/second.yml')
61
+
62
+ # You can load only YAML part (root: 'config')
63
+ part1 = Settings::Config.create { merge_storage file, root: 'config' }
64
+ puts part1.param1 # => config/param1
65
+
66
+ # Or load even more deeper (root: 'Config/param3')
67
+ part2 = Settings::Config.create { merge_storage file, root: 'Config/param3' }
68
+ print part2.super_deep_array # => [1, 2, 3, 4]
69
+ ```
70
+
71
+ ### SAMPLE 3. PROVIDERS
72
+
73
+ ```ruby
74
+ ## PART 1 ENV
75
+
76
+ dynamic = Settings::Config.create do
77
+ merge_storage Settings::ENV.load( RbConfig::CONFIG )
78
+ end
79
+
80
+ puts dynamic["RUBY_VERSION_NAME"] # => ruby-2.3.0
81
+
82
+ ## PART 2 YAML
83
+
84
+ yaml = Settings::Config.create do
85
+ merge_storage Settings::Yaml.load('../configs/second.yml')
86
+ end
87
+
88
+ puts yaml[:config][:param1] # => config/param1
89
+ ```
90
+
91
+ ## dependencies
92
+
93
+ > Ruby 2.0.0 or higher
94
+
95
+ ## License
96
+ ----
97
+
98
+ MIT, see [LICENSE](./LICENSE)
@@ -0,0 +1,32 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Settings::Config do
6
+ context '#create' do
7
+ it 'raises an NoBlockGiven exception when method was called without &block' do
8
+ expect { Settings::Config.create }.to raise_error Settings::Config::NoBlockGiven
9
+ end
10
+ end # context '#create'
11
+
12
+ context 'after #create' do
13
+ before :each do
14
+ @subject = described_class.create do
15
+ merge_storage Settings::ENV.load(param1: 'sample')
16
+ end
17
+ end
18
+
19
+ context '#method_missing' do
20
+ it 'redirect message call to storage when it needed' do
21
+ expect(@subject.param1).to_not be_nil
22
+ end
23
+ end # context "#method_missing"
24
+
25
+ context '#respond_to?' do
26
+ it 'redirect response_to? message call to storage when it needed' do
27
+ expect(@subject.send(:respond_to?, :param1)).to be_truthy
28
+ end
29
+ end # context 'respond_to?'
30
+ end # context 'after #create'
31
+
32
+ end # describe Settings::Config
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Settings::ENV do
6
+ let (:valid_hsh_sample) { {string: 'some_string', param: true } }
7
+ let (:not_hsh_sample) { Time.new }
8
+
9
+ context '#load' do
10
+ it 'raises an HashNotValid exception for object that not is a hash' do
11
+ expect { described_class.load(not_hsh_sample) }
12
+ .to raise_error Settings::ENV::HashNotValid
13
+ end
14
+
15
+ it 'saves valid hash into .data field' do
16
+ obj = described_class.load valid_hsh_sample
17
+ expect(obj.data.length).to be > 0
18
+ end
19
+ end # context '#load'
20
+ end # describe Settings::ENV
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Settings::Yaml do
6
+ let(:valid_file_path) { File.join RSpec::Core::RubyProject.root, 'configs', 'first.yml' }
7
+
8
+ context 'load' do
9
+ it 'loads a hash from file' do
10
+ provider = described_class.load(valid_file_path)
11
+ expect(provider.data.length).to be > 0
12
+ end
13
+
14
+ it 'raises FileNotFound exception when file not found' do
15
+ expect { described_class.load('file_that_can_not_exist') }
16
+ .to raise_error Settings::Yaml::FileNotFound
17
+ end
18
+ end # context 'load' do
19
+
20
+ end # describe Settings::Yaml
@@ -0,0 +1,34 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Settings::Config do
6
+ context 'Provider module' do
7
+
8
+ context '#merge_storage' do
9
+ it 'raises an ProviderNotRespond exception when provider does not respond to :load method' do
10
+ expect do
11
+ Settings::Config.create { merge_storage 'string_as_provider' }
12
+ end.to raise_error Settings::Config::ProviderNotRespond
13
+ end
14
+ end # context '#merge_storage'
15
+
16
+ context '#extract_sub_hash_from' do
17
+ it 'raises an RootNotExist exception when provider can not extract a hash' do
18
+ provider = Settings::ENV.load(param1: true, para2: false)
19
+ expect do
20
+ Settings::Config.create { merge_storage(provider, root: 'wrong/path') }
21
+ end.to raise_error Settings::Provider::RootNotExist
22
+ end
23
+ end # context '#extract_sub_hash_from'
24
+
25
+ context '#validate_and_extract_hash_from' do
26
+ it 'raises an HashNotValid exception when provider getting empty hash' do
27
+ expect do
28
+ Settings::Config.create { merge_storage Settings::ENV.load({}) }
29
+ end.to raise_error Settings::Config::HashNotValid
30
+ end
31
+ end # context '#validate_and_extract_hash_from'
32
+
33
+ end # context '#provider'
34
+ end # describe Settings::Config
@@ -0,0 +1,69 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Settings::Storage do
6
+ let(:hsh_sample) do
7
+ { nested_hsh: { param1: true, param2: false },
8
+ param1: 42,
9
+ param2: 15,
10
+ predicate: true,
11
+ 'special_sample' => { 55 => 'good' } }
12
+ end
13
+
14
+ subject { described_class.new(hsh_sample) }
15
+
16
+ describe 'Storage' do
17
+ context 'after #create' do
18
+ it 'registers hash key as predicate method for booleans' do
19
+ expect(subject.predicate?).to be_truthy
20
+ end
21
+
22
+ it 'have a correct value assigned with registered method' do
23
+ expect(subject.param1).to eql(42)
24
+ end
25
+
26
+ context '#[]' do
27
+ it 'raises an ValueNotFound exception when argument for [] not valid' do
28
+ expect { subject[:param42] }
29
+ .to raise_error(Settings::Storage::ValueNotFound)
30
+ end
31
+
32
+ it 'gives value by access throw [] method' do
33
+ expect(subject[:param2]).to eql(15)
34
+ end
35
+
36
+ it 'provides chain call throw [] method' do
37
+ expect(subject[:nested_hsh][:param2]).to eql(false)
38
+ end
39
+
40
+ it 'allows to use numbers and strings as parameters' do
41
+ expect(subject['special_sample'][55]).to eql('good')
42
+ end
43
+ end # context "#[]"
44
+
45
+ context '#fill_in_storage' do
46
+ it 'registers hash key as method' do
47
+ expect(subject.send(:respond_to?, :param1)).to be_truthy
48
+ end
49
+
50
+ it 'registers a sub-storage for sub-hash' do
51
+ expect(subject.nested_hsh).to be_an_instance_of(Settings::Storage)
52
+ end
53
+ end # context "#fill_in_storage"
54
+
55
+ context '#method_missing' do
56
+ it 'redirect message call to sub-storage' do
57
+ expect(subject.nested_hsh.param1).to_not be_nil
58
+ end
59
+ end # context "#method_missing"
60
+
61
+ context '#respond_to?' do
62
+ it 'redirect response_to? message call to sub-storage' do
63
+ expect(subject.send(:respond_to?, :nested_hsh)).to be_truthy
64
+ end
65
+ end # context 'respond_to?'
66
+ end # context 'after #create'
67
+
68
+ end # describe "Storage"
69
+ end # describe Settings::Storage
@@ -0,0 +1,6 @@
1
+ # encoding: utf-8
2
+
3
+ require_relative '../lib/configurates'
4
+
5
+ RSpec.configure do |config|
6
+ end
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: configurates
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.1
5
+ platform: ruby
6
+ authors:
7
+ - Kuzichev Michael
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-09-07 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email: kMedvedu@gmail.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - Gemfile
20
+ - LICENSE
21
+ - Rakefile
22
+ - lib/configurates.rb
23
+ - lib/configurates/provider.rb
24
+ - lib/configurates/provider/environment.rb
25
+ - lib/configurates/provider/yaml.rb
26
+ - lib/configurates/storage.rb
27
+ - readme.md
28
+ - spec/config_spec.rb
29
+ - spec/customizable_configuration/provider/environment_spec.rb
30
+ - spec/customizable_configuration/provider/yaml_spec.rb
31
+ - spec/customizable_configuration/provider_spec.rb
32
+ - spec/customizable_configuration/storage_spec.rb
33
+ - spec/spec_helper.rb
34
+ homepage: https://github.com/Medvedu/customizable_configuration
35
+ licenses:
36
+ - MIT
37
+ metadata: {}
38
+ post_install_message:
39
+ rdoc_options: []
40
+ require_paths:
41
+ - lib
42
+ required_ruby_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 2.0.0
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ requirements: []
53
+ rubyforge_project:
54
+ rubygems_version: 2.6.4
55
+ signing_key:
56
+ specification_version: 4
57
+ summary: configurates is a lib that provides agile way to work with configuration,
58
+ which can be useful for object initialization
59
+ test_files:
60
+ - spec/spec_helper.rb
61
+ - spec/customizable_configuration/storage_spec.rb
62
+ - spec/customizable_configuration/provider_spec.rb
63
+ - spec/customizable_configuration/provider/environment_spec.rb
64
+ - spec/customizable_configuration/provider/yaml_spec.rb
65
+ - spec/config_spec.rb
66
+ has_rdoc: