configatron 3.2.0 → 4.5.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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +2 -2
  4. data/History.txt +72 -0
  5. data/README.md +25 -24
  6. data/Rakefile +10 -4
  7. data/configatron.gemspec +1 -0
  8. data/lib/configatron.rb +22 -4
  9. data/lib/configatron/core.rb +6 -6
  10. data/lib/configatron/ext/kernel.rb +5 -0
  11. data/lib/configatron/integrations.rb +4 -0
  12. data/lib/configatron/integrations/minitest.rb +29 -0
  13. data/lib/configatron/{rails.rb → integrations/rails.rb} +1 -1
  14. data/lib/configatron/root_store.rb +121 -0
  15. data/lib/configatron/store.rb +104 -67
  16. data/lib/configatron/version.rb +1 -1
  17. data/lib/generators/configatron/install/templates/configatron/defaults.rb +2 -2
  18. data/lib/generators/configatron/install/templates/configatron/development.rb +2 -2
  19. data/lib/generators/configatron/install/templates/configatron/production.rb +2 -2
  20. data/lib/generators/configatron/install/templates/configatron/test.rb +2 -2
  21. data/lib/generators/configatron/install/templates/initializers/configatron.rb +1 -1
  22. data/test/_lib.rb +17 -0
  23. data/test/functional/_lib.rb +10 -0
  24. data/test/functional/_lib/scripts/core.rb +11 -0
  25. data/test/functional/configatron.rb +165 -0
  26. data/test/functional/delayed.rb +18 -0
  27. data/test/functional/loading.rb +10 -0
  28. data/test/functional/minitest.rb +18 -0
  29. data/test/unit/_lib.rb +10 -0
  30. data/test/unit/configatron/proc.rb +24 -0
  31. data/test/unit/configatron/root_store.rb +37 -0
  32. data/test/unit/configatron/store.rb +149 -0
  33. metadata +55 -28
  34. data/.ruby-version +0 -1
  35. data/lib/configatron/deep_clone.rb +0 -69
  36. data/lib/configatron/kernel.rb +0 -21
  37. data/test/configatron/kernel_test.rb +0 -24
  38. data/test/configatron/proc_test.rb +0 -27
  39. data/test/configatron/store_test.rb +0 -256
  40. data/test/configatron_test.rb +0 -5
  41. data/test/test_helper.rb +0 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1dc9cfe0ed3b4c2c0c90b325d4b837e4aed30d8b
4
- data.tar.gz: 6bd11604cc4abf42aa461f33970e0935580774a7
3
+ metadata.gz: 132989ab43482032a4a574c7c165e382bd361fb8
4
+ data.tar.gz: e6774fccb00c33995c109f8ce62e05caa87bebd8
5
5
  SHA512:
6
- metadata.gz: 8f4c42d22a0fa92b539c716aa2fcb53e3b837cf843f6fde91114823d8a5f2eb9c022d1712af686fadab9a3d1604ae746f2f64d626d4c4fa298b9d192f6e18823
7
- data.tar.gz: 6ba36b1929bf8fad1774f10c309b145f3cddd01371a2d2b81213dc92f3d7446a03d18255425c8ffbf48649100c3535e54dfa39a080e37ad8f9200c60be7125cc
6
+ metadata.gz: 4f94da811e4b3add13ef0ae54ade8c6202568eeee89d0b1f803980b1ca1f25d968e99793c515de95566715a7a611a16ca0f2a19c1107f1bf650fd2b650b3381a
7
+ data.tar.gz: f90d0c18873c458a933e26d58f30eda5e712a7e2f6e34bc752dace68604f4eab75062fd3ac9eb7052afe7bcedc6d1c76ca8f99a9af47a29aade4abcc6114c9b9
data/.gitignore CHANGED
@@ -15,6 +15,7 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ .ruby-version
18
19
 
19
20
  .DS_Store
20
21
  *.rbc
data/.travis.yml CHANGED
@@ -4,5 +4,5 @@ rvm:
4
4
  - 2.0.0
5
5
  - 2.1.0
6
6
  - 2.1.1
7
- install: bundle install
8
- script: bundle exec rake
7
+ install: travis_retry bundle install
8
+ script: bundle exec rake test
data/History.txt ADDED
@@ -0,0 +1,72 @@
1
+ === 4.5.0
2
+
3
+ * [backwards-incompatible] Switch from DeepClone to copy-on-write for temp. As part of the implementation, *values* are no longer cloned.
4
+
5
+ === 4.4.1
6
+
7
+ * Make lock!/unlock! support blocks
8
+
9
+ === 4.4.0
10
+
11
+ * [backwards-incompatible] Make temp preserve locking state across invocations
12
+
13
+ === 4.3.0
14
+
15
+ * [backwards-incompatible] Make nil into a valid config value
16
+ * [backwards-incompatible] Make temp clean up after itself when an exception is thrown
17
+
18
+ === 4.2.1
19
+
20
+ * Fix a bug with deep cloning which caused temping to break for nested settings
21
+
22
+ === 4.2.0
23
+
24
+ * [backwards-incompatible] Make to_h/to_hash recursively hashify Configatron::Stores, and resolve Configatron::Procs.
25
+
26
+ === 4.1.1
27
+
28
+ * Fix delayed attributes
29
+
30
+ === 4.1.0
31
+
32
+ * Fix bugs from BasicObject fallout
33
+ * Have KernelStore proxy calls using `public_send` for consistent shadowing
34
+
35
+ === 4.0.3
36
+
37
+ * Switch Store and RootStore to descend from BasicObject
38
+
39
+ === 4.0.2
40
+
41
+ * Add missing require of Rails integration
42
+
43
+ === 4.0.1
44
+
45
+ * Fix #inspect and #to_s methods on KernelStore to pass through to Store
46
+
47
+ === 4.0.0
48
+
49
+ This is largely a restructuring of existing functionality, making it
50
+ simpler and more consistent. The tests have also been fully
51
+ refactored.
52
+
53
+ Added the following:
54
+
55
+ * A Minitest integration at Configatron::Integrations::Minitest
56
+ * Key errors while locked return the name of the relevant configatron
57
+ * Configatron::RootStore is now the intended way to start a new configatron hiearchy. (You should likely not initialize a Configatron::Store yourself.)
58
+
59
+ Deprecated the following:
60
+
61
+ * Initializing a Configatron::Store with a custom hash
62
+ * Calling .nil?/.empty? on a Configatron::Store
63
+ * Calling locking, temp, or reset methods directly on a Configatron::Store (moved instead to Configatron::RootStore)
64
+ * A DeepClone module is no longer defined at the top-level
65
+ * Removed Configatron::KernelStore
66
+
67
+ Other backwards-incompatible changes:
68
+
69
+ * Renamespaced Configatron::Rails under Configatron::Integrations::Rails.
70
+ * Moved locking and temp methods to exist just on Configatron::RootStore.
71
+ * Configatron::Store.inspect no longer takes a name
72
+ * key? will now return true for sub-Configatron::Stores
data/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  Configatron makes configuring your applications and scripts incredibly easy. No longer is a there a need to use constants or global variables. Now you can use a simple and painless system to configure your life. And, because it's all Ruby, you can do any crazy thing you would like to!
5
5
 
6
- One of the more important changes to V3 is that it now resembles more a `Hash` style interface. You can use `[]`, `fetch`, `each`, etc...
6
+ One of the more important changes to V3 is that it now resembles more a `Hash` style interface. You can use `[]`, `fetch`, `each`, etc... Actually the hash notation is a bit more robust since the dot notation won't work for a few property names (a few public methods from `Configatron::Store` itself).
7
7
 
8
8
  ## Installation
9
9
 
@@ -66,7 +66,7 @@ Notice how our other configuration parameters haven't changed? Cool, eh?
66
66
 
67
67
  ### Hash/YAML
68
68
 
69
- You can configure Configatron from a hash as well (this is really only useful in testing or for data driven configuration, it's not recommended for actual configuration):
69
+ You can configure Configatron from a hash as well (this is particularly useful if you'd like to have configuration files):
70
70
 
71
71
  ```ruby
72
72
  configatron.configure_from_hash(email: {pop: {address: 'pop.example.com', port: 110}}, smtp: {address: 'smtp.example.com'})
@@ -76,9 +76,11 @@ configatron.email.pop.port # => 110
76
76
  # and so on...
77
77
  ```
78
78
 
79
- #### YAML
79
+ ### Method vs hash access
80
80
 
81
- YAML is terrible and should be driven from the face of the Earth. Because of this Configatron V3 does not support it. Sorry.
81
+ As a note, method (`configatron.foo`) access will be shadowed by public methods defined on the configatron object. (The configatron object descends from [`BasicObject`](http://apidock.com/ruby/BasicObject) and adds a few methods to resemble the `Hash` API and to play nice with `puts`, so it should have a pretty bare set of methods.)
82
+
83
+ If you need to use keys that are themselves method names, you can just use hash access (`configatron['foo']`).
82
84
 
83
85
  ### Namespaces
84
86
 
@@ -119,7 +121,7 @@ end
119
121
 
120
122
  ### Temp Configurations
121
123
 
122
- Sometimes in testing, or other situations, you want to temporarily change some settings. You can do this with the `temp` method:
124
+ Sometimes in testing, or other situations, you want to temporarily change some settings. You can do this with the `temp` method (only available on the top-level configatron `RootStore`):
123
125
 
124
126
  ```ruby
125
127
  configatron.one = 1
@@ -189,17 +191,17 @@ configatron.current.time = Configatron::Dynamic.new {Time.now}
189
191
 
190
192
  Each time you call `configatron.current.time` it will return a new value to you. While this seems a bit useless, it is pretty useful if you have ever changing configurations.
191
193
 
192
- ### nil
194
+ ### Reseting Configurations
193
195
 
194
- Even if parameters haven't been set, you can still call them, but you'll get a `Configatron::Store` object back. The `Configatron::Store` class, however, will respond true to `.nil?` or `.blank?` if there are no parameters configured on it.
196
+ In some testing scenarios, it can be helpful to restore Configatron to its default state. This can be done with:
195
197
 
196
198
  ```ruby
197
- configatron.i.dont.exist.nil? # => true
198
- configatron.i.dont.exist.blank? # => true
199
- configatron.i.dont.exist # => Configatron::Store
200
- ```
199
+ configatron.reset!
200
+ ```
201
+
202
+ ### Checking keys
201
203
 
202
- You can use `.has_key?` to determine if a key already exists.
204
+ Even if parameters haven't been set, you can still call them, but you'll get a `Configatron::Store` object back. You can use `.has_key?` to determine if a key already exists.
203
205
 
204
206
  ```ruby
205
207
  configatron.i.dont.has_key?(:exist) # => false
@@ -218,16 +220,14 @@ configatron.a.b.c! # => raise Configratron::UndefinedKeyError
218
220
 
219
221
  ### Kernel
220
222
 
221
- The `configatron` "helper" method is store in the `Kernel` module. Some people didn't like that in the V2 of Configatron, so in V3, while that hasn't changed, you don't have to use it.
222
-
223
- Instead of requiring `configatron` simply require `configatron/core`, but then you'll have to set up your own `Configatron::Store` object.
223
+ The `configatron` "helper" method is stored in the `Kernel` module. You can opt-out of this global monkey-patching by requiring `configatron/core` rather than `configatron`. You'll have to set up your own `Configatron::RootStore` object.
224
224
 
225
225
  Example:
226
226
 
227
227
  ```ruby
228
228
  require 'configatron/core'
229
229
 
230
- store = Configatron::Store.new
230
+ store = Configatron::RootStore.new
231
231
  store.foo = 'FOO'
232
232
 
233
233
  store.to_h #= {foo: 'FOO'}
@@ -289,23 +289,24 @@ configatron.to_h # => {:letters=>{:a=>"A", :b=>"BB", :c=>"C"}}
289
289
  ## Contributors
290
290
 
291
291
  * Mark Bates
292
+ * Greg Brockman
292
293
  * Kurtis Rainbolt-Greene
293
294
  * Rob Sanheim
294
- * Greg Brockman
295
295
  * Jérémy Lecour
296
296
  * Cody Maggard
297
297
  * Jean-Denis Vauguet
298
- * Torsten Schönebaum
299
- * Simon Menke
300
- * Gleb Pomykalov
301
298
  * chatgris
299
+ * Simon Menke
302
300
  * Mat Brown
301
+ * Torsten Schönebaum
302
+ * Gleb Pomykalov
303
303
  * Casper Gripenberg
304
- * Dan Pickett
305
304
  * Artiom Diomin
306
- * Tim Riley
307
305
  * mattelacchiato
308
- * joe miller
309
- * Brandon Dimcheff
306
+ * Dan Pickett
307
+ * Tim Riley
310
308
  * Rick Fletcher
309
+ * Jose Antonio Pio
310
+ * Brandon Dimcheff
311
+ * joe miller
311
312
  * Josh Nichols
data/Rakefile CHANGED
@@ -3,7 +3,13 @@ require 'rake/testtask'
3
3
 
4
4
  Bundler::GemHelper.install_tasks
5
5
 
6
- Rake::TestTask.new(:default) do |t|
7
- t.libs << "test"
8
- t.test_files = FileList["test/**/*_test.rb"]
9
- end
6
+ Rake::TestTask.new do |t|
7
+ t.libs = ["lib"]
8
+ # t.warning = true
9
+ t.verbose = true
10
+ t.test_files = FileList['test/**/*.rb'].reject do |file|
11
+ file.end_with?('_lib.rb') || file.include?('/_lib/')
12
+ end
13
+ end
14
+
15
+ task :default => :test
data/configatron.gemspec CHANGED
@@ -20,5 +20,6 @@ Gem::Specification.new do |gem|
20
20
 
21
21
  gem.add_development_dependency "rake"
22
22
  gem.add_development_dependency "mocha"
23
+ gem.add_development_dependency "subprocess"
23
24
  gem.add_development_dependency "minitest", '>=5.2.3'
24
25
  end
data/lib/configatron.rb CHANGED
@@ -1,5 +1,23 @@
1
- require 'singleton'
2
1
  require 'configatron/version'
3
- require 'configatron/kernel'
4
- require 'configatron/core'
5
- require 'configatron/rails'
2
+
3
+ require 'configatron/errors'
4
+ require 'configatron/integrations'
5
+ require 'configatron/root_store'
6
+ require 'configatron/store'
7
+
8
+ # Proc *must* load before dynamic/delayed, or else Configatron::Proc
9
+ # will refer to the global ::Proc
10
+ require 'configatron/proc'
11
+ require 'configatron/delayed'
12
+ require 'configatron/dynamic'
13
+
14
+ class Configatron
15
+ end
16
+
17
+ # NO_EXT gets defined when you require "configatron/core", which
18
+ # signals that you don't want any extensions. It'd be nice to have a
19
+ # better internal signaling mechanism (could use environment
20
+ # variables, but then they become part of the public interface).
21
+ unless defined?(Configatron::NO_EXT)
22
+ require 'configatron/ext/kernel'
23
+ end
@@ -1,6 +1,6 @@
1
- require_relative "deep_clone"
2
- require_relative "store"
3
- require_relative "errors"
4
- require_relative "proc"
5
- require_relative "dynamic"
6
- require_relative "delayed"
1
+ class Configatron
2
+ # Signals that we should not load the extensions.
3
+ NO_EXT = true
4
+ end
5
+
6
+ require 'configatron'
@@ -0,0 +1,5 @@
1
+ module Kernel
2
+ def configatron
3
+ Configatron::RootStore.instance
4
+ end
5
+ end
@@ -0,0 +1,4 @@
1
+ module Configatron::Integrations; end
2
+
3
+ require 'configatron/integrations/minitest'
4
+ require 'configatron/integrations/rails'
@@ -0,0 +1,29 @@
1
+ # Include in a minitest to restore the global configatron object to
2
+ # its global state afterwards. Particularly useful if you'd like to test
3
+ # your application with various config settings.
4
+ #
5
+ # ```ruby
6
+ # class Test::Suite < Minitest::Unit
7
+ # include Configatron::Integrations::Minitest
8
+ #
9
+ # it 'works' do
10
+ # configatron.unlock! do
11
+ # configatron.some.setting = true
12
+ # end
13
+ #
14
+ # [...]
15
+ # end
16
+ # ```
17
+ module Configatron::Integrations
18
+ module Minitest
19
+ def before_setup
20
+ configatron.temp_start
21
+ super
22
+ end
23
+
24
+ def before_teardown
25
+ super
26
+ configatron.temp_end
27
+ end
28
+ end
29
+ end
@@ -1,4 +1,4 @@
1
- class Configatron
1
+ module Configatron::Integrations
2
2
  # Helpful for making using configatron with Rails even easier!
3
3
  #
4
4
  # To get started you can use the generator to generate
@@ -0,0 +1,121 @@
1
+ require 'singleton'
2
+ require 'forwardable'
3
+
4
+ # This is the root configatron object, and contains methods which
5
+ # operate on the entire configatron hierarchy.
6
+ class Configatron::RootStore < BasicObject
7
+ include ::Singleton
8
+ extend ::Forwardable
9
+
10
+ attr_reader :store
11
+
12
+ # Have one global RootStore instance, but allow people to create
13
+ # their own parallel ones if they desire.
14
+ class << self
15
+ public :new
16
+ end
17
+
18
+ @@cow = 0
19
+
20
+ def initialize
21
+ @locked = false
22
+ @cow = nil
23
+ reset!
24
+ end
25
+
26
+ def __cow
27
+ @cow
28
+ end
29
+
30
+ def __cow_path(path)
31
+ start = @store.__cow_clone
32
+
33
+ node = start
34
+ branch = path.map do |key|
35
+ node = node[key]
36
+ node.__cow_clone
37
+ end
38
+ nodes = [start] + branch
39
+
40
+ # [node1, node2, node3] with
41
+ # [node2, node3, node4] and
42
+ # ['key1', 'key2, 'key3']
43
+ nodes[0...-1].zip(nodes[1..-1], path) do |parent, child, key|
44
+ # These are all cow_clones, so won't trigger a further cow
45
+ # modification.
46
+ parent[key] = child
47
+ end
48
+
49
+ @store = nodes.first
50
+ nodes.last
51
+ end
52
+
53
+ def method_missing(name, *args, &block)
54
+ store.__send__(name, *args, &block)
55
+ end
56
+
57
+ def reset!
58
+ @store = ::Configatron::Store.new(self)
59
+ end
60
+
61
+ def temp(&block)
62
+ temp_start
63
+
64
+ begin
65
+ yield
66
+ ensure
67
+ temp_end
68
+ end
69
+ end
70
+
71
+ def temp_start
72
+ @temp_locked = @locked
73
+ @temp_cow = @cow
74
+
75
+ # Just need to have a unique Copy-on-Write generation ID
76
+ @cow = @@cow += 1
77
+ @temp = @store
78
+ end
79
+
80
+ def temp_end
81
+ @locked = @temp_locked
82
+ @cow = @temp_cow
83
+
84
+ @store = @temp
85
+ end
86
+
87
+ def locked?
88
+ @locked
89
+ end
90
+
91
+ def lock!(&blk)
92
+ if blk
93
+ orig = @locked
94
+ begin
95
+ @locked = true
96
+ blk.call
97
+ ensure
98
+ @locked = orig
99
+ end
100
+ else
101
+ @locked = true
102
+ end
103
+ end
104
+
105
+ def unlock!(&blk)
106
+ if blk
107
+ orig = @locked
108
+ begin
109
+ @locked = false
110
+ blk.call
111
+ ensure
112
+ @locked = orig
113
+ end
114
+ else
115
+ @locked = false
116
+ end
117
+ end
118
+
119
+ def_delegator :@store, :to_s
120
+ def_delegator :@store, :inspect
121
+ end