configatron 3.2.0 → 4.5.1

Sign up to get free protection for your applications and to get access to all the features.
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