configatron 4.1.0 → 4.1.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.
data/History.txt CHANGED
@@ -1,3 +1,7 @@
1
+ === 4.1.1
2
+
3
+ * Fix delayed attributes
4
+
1
5
  === 4.1.0
2
6
 
3
7
  * Fix bugs from BasicObject fallout
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... Actually the hash notation is more robust since the dot notation won't work for some property names. See section "Differences between dot and hash notation" for more details.
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
 
@@ -78,7 +78,7 @@ configatron.email.pop.port # => 110
78
78
 
79
79
  ### Method vs hash access
80
80
 
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 includes `Kernel`, so it should have a pretty bare set of methods.)
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
82
 
83
83
  If you need to use keys that are themselves method names, you can just use hash access (`configatron['foo']`).
84
84
 
@@ -35,30 +35,32 @@ module Configatron::DeepClone
35
35
  # You can redistribute it and/or modify it under the same terms of Ruby's license;
36
36
  # either the dual license version in 2003, or any later version.
37
37
  def self.deep_clone( obj=self, cloned={} )
38
- if obj.kind_of?(Configatron::RootStore)
38
+ if Configatron::RootStore === obj
39
39
  # We never actually want to have multiple copies of our
40
40
  # Configatron::RootStore (and every Store has a reference).
41
41
  return obj
42
- elsif cloned.has_key?( obj.object_id )
43
- return cloned[obj.object_id]
42
+ elsif cloned.key?( obj.__id__ )
43
+ return cloned[obj.__id__]
44
44
  else
45
45
  begin
46
46
  cl = obj.clone
47
47
  rescue Exception
48
48
  # unclonnable (TrueClass, Fixnum, ...)
49
- cloned[obj.object_id] = obj
49
+ cloned[obj.__id__] = obj
50
50
  return obj
51
51
  else
52
- cloned[obj.object_id] = cl
53
- cloned[cl.object_id] = cl
54
- if cl.is_a?( Hash )
55
- cl.clone.each { |k,v|
52
+ cloned[obj.__id__] = cl
53
+ cloned[cl.__id__] = cl
54
+ case
55
+ when Configatron::Store === cl then return cl
56
+ when Hash === cl
57
+ cl.clone.each do |k,v|
56
58
  cl[k] = deep_clone( v, cloned )
57
- }
58
- elsif cl.is_a?( Array )
59
- cl.collect! { |v|
59
+ end
60
+ when Array === cl
61
+ cl.collect! do |v|
60
62
  deep_clone( v, cloned )
61
- }
63
+ end
62
64
  end
63
65
  cl.instance_variables.each do |var|
64
66
  v = cl.instance_eval( var.to_s )
@@ -3,7 +3,6 @@ require 'singleton'
3
3
  # This is the root configatron object, and contains methods which
4
4
  # operate on the entire configatron hierarchy.
5
5
  class Configatron::RootStore < BasicObject
6
- include ::Kernel
7
6
  include ::Singleton
8
7
  extend ::Forwardable
9
8
 
@@ -21,7 +20,7 @@ class Configatron::RootStore < BasicObject
21
20
  end
22
21
 
23
22
  def method_missing(name, *args, &block)
24
- store.public_send(name, *args, &block)
23
+ store.__send__(name, *args, &block)
25
24
  end
26
25
 
27
26
  def reset!
@@ -2,7 +2,6 @@ require 'forwardable'
2
2
 
3
3
  class Configatron
4
4
  class Store < BasicObject
5
- include ::Kernel
6
5
  extend ::Forwardable
7
6
 
8
7
  def initialize(root_store, name='configatron', attributes={})
@@ -14,7 +13,7 @@ class Configatron
14
13
  def [](key)
15
14
  val = fetch(key.to_sym) do
16
15
  if @root_store.locked?
17
- raise ::Configatron::UndefinedKeyError.new("Key not found: #{key} (for locked #{self})")
16
+ ::Kernel.raise ::Configatron::UndefinedKeyError.new("Key not found: #{key} (for locked #{self})")
18
17
  end
19
18
  ::Configatron::Store.new(@root_store, "#{@name}.#{key}")
20
19
  end
@@ -23,22 +22,22 @@ class Configatron
23
22
 
24
23
  def store(key, value)
25
24
  if @root_store.locked?
26
- raise ::Configatron::LockedError.new("Cannot set key #{key} for locked #{self}")
25
+ ::Kernel.raise ::Configatron::LockedError.new("Cannot set key #{key} for locked #{self}")
27
26
  end
28
27
  @attributes[key.to_sym] = value
29
28
  end
30
29
 
31
30
  def fetch(key, default_value = nil, &block)
32
31
  val = @attributes[key.to_sym]
33
- if val.nil?
34
- if block_given?
32
+ if val == nil
33
+ if block
35
34
  val = block.call
36
35
  elsif default_value
37
36
  val = default_value
38
37
  end
39
38
  store(key, val)
40
39
  end
41
- if val.is_a?(::Configatron::Proc)
40
+ if ::Configatron::Proc === val
42
41
  val = val.call
43
42
  end
44
43
  return val
@@ -50,7 +49,7 @@ class Configatron
50
49
 
51
50
  def configure_from_hash(hash)
52
51
  hash.each do |key, value|
53
- if value.is_a?(::Hash)
52
+ if ::Hash === value
54
53
  self[key].configure_from_hash(value)
55
54
  else
56
55
  store(key, value)
@@ -65,7 +64,7 @@ class Configatron
65
64
  def inspect
66
65
  f_out = []
67
66
  @attributes.each do |k, v|
68
- if v.is_a?(::Configatron::Store)
67
+ if ::Configatron::Store === v
69
68
  v.inspect.each_line do |line|
70
69
  if line.match(/\n/)
71
70
  line.each_line do |l|
@@ -85,25 +84,23 @@ class Configatron
85
84
  end
86
85
 
87
86
  def method_missing(name, *args, &block)
88
- # Needed to allow 'puts'ing of a configatron.
89
- if name == :to_ary
90
- raise ::NoMethodError.new("Called :to_ary")
91
- end
92
-
93
- # In case of Configatron bugs, prevent method_missing infinite
94
- # loops.
95
- if @method_missing
96
- raise ::NoMethodError.new("Bug in configatron; ended up in method_missing while running: #{name.inspect}")
97
- end
98
- @method_missing = true
99
87
  do_lookup(name, *args, &block)
100
- ensure
101
- @method_missing = false
102
88
  end
103
89
 
104
90
  # Needed for deep_clone to actually clone this object
105
91
  def clone
106
- self.class.new(@root_store, @name, @attributes)
92
+ Store.new(@root_store, @name, @attributes.clone)
93
+ end
94
+
95
+ # So that puts works (it expects the object to respond to to_ary)
96
+ def to_ary
97
+ nil
98
+ end
99
+
100
+ # So that we keep backward-compatibility in case people are using nil? to check
101
+ # configatron settings:
102
+ def nil?
103
+ false
107
104
  end
108
105
 
109
106
  private
@@ -120,7 +117,7 @@ class Configatron
120
117
  if self.has_key?(key)
121
118
  return self[key]
122
119
  else
123
- raise ::Configatron::UndefinedKeyError.new($1)
120
+ ::Kernel.raise ::Configatron::UndefinedKeyError.new($1)
124
121
  end
125
122
  else
126
123
  return self[name]
@@ -1,3 +1,3 @@
1
1
  class Configatron
2
- VERSION = "4.1.0"
2
+ VERSION = "4.1.1"
3
3
  end
@@ -3,5 +3,5 @@
3
3
  # Example:
4
4
  # configatron.emails.welcome.subject = 'Welcome!'
5
5
  # configatron.emails.sales_reciept.subject = 'Thanks for your order'
6
- #
7
- # configatron.file.storage = :s3
6
+ #
7
+ # configatron.file.storage = :s3
@@ -1,4 +1,4 @@
1
1
  # Override your default settings for the Development environment here.
2
- #
2
+ #
3
3
  # Example:
4
- # configatron.file.storage = :local
4
+ # configatron.file.storage = :local
@@ -1,4 +1,4 @@
1
1
  # Override your default settings for the Production environment here.
2
- #
2
+ #
3
3
  # Example:
4
- # configatron.file.storage = :s3
4
+ # configatron.file.storage = :s3
@@ -1,4 +1,4 @@
1
1
  # Override your default settings for the Test environment here.
2
- #
2
+ #
3
3
  # Example:
4
- # configatron.file.storage = :local
4
+ # configatron.file.storage = :local
@@ -1,4 +1,2 @@
1
1
  require 'configatron'
2
- require 'configatron/integrations/rails'
3
-
4
2
  Configatron::Integrations::Rails.init
@@ -51,15 +51,19 @@ class Critic::Functional::ConfigatronTest < Critic::Functional::Test
51
51
  end
52
52
 
53
53
  it 'raises an error when accessing non-existing values' do
54
- refute_nil(@kernel.a)
55
- refute_nil(@kernel.a.b)
56
- refute_nil(@kernel.a.b.c)
54
+ assert @kernel.a != nil
55
+ assert @kernel.a.b != nil
56
+ assert @kernel.a.b.c != nil
57
57
  assert_equal('DD', @kernel.a.b.c.d)
58
58
  assert_raises(Configatron::UndefinedKeyError) do
59
59
  @kernel.unknown
60
60
  end
61
61
  end
62
62
 
63
+ it 'responds to nil? for backward compatibility' do
64
+ refute_nil @kernel.a
65
+ end
66
+
63
67
  it 'raises an error when trying to set a non-existing key' do
64
68
  assert_raises(Configatron::LockedError) do
65
69
  @kernel.unknown = 'known'
@@ -0,0 +1,18 @@
1
+ require_relative '_lib'
2
+
3
+ class Critic::Functional::DelayedTest < Critic::Functional::Test
4
+ before do
5
+ @kernel = Configatron::RootStore.new
6
+ end
7
+
8
+ describe 'delayed' do
9
+ before do
10
+ @kernel.a = Configatron::Delayed.new { @kernel.b }
11
+ @kernel.b = "expected"
12
+ end
13
+
14
+ it 'works independent of the order' do
15
+ assert_equal('expected', @kernel.a)
16
+ end
17
+ end
18
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: configatron
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.0
4
+ version: 4.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-06-17 00:00:00.000000000 Z
12
+ date: 2014-06-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -116,6 +116,7 @@ files:
116
116
  - test/functional/_lib.rb
117
117
  - test/functional/_lib/scripts/core.rb
118
118
  - test/functional/configatron.rb
119
+ - test/functional/delayed.rb
119
120
  - test/functional/loading.rb
120
121
  - test/functional/minitest.rb
121
122
  - test/unit/_lib.rb
@@ -137,7 +138,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
137
138
  version: '0'
138
139
  segments:
139
140
  - 0
140
- hash: 201983176826574058
141
+ hash: 2777108850332874749
141
142
  required_rubygems_version: !ruby/object:Gem::Requirement
142
143
  none: false
143
144
  requirements:
@@ -146,7 +147,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
146
147
  version: '0'
147
148
  segments:
148
149
  - 0
149
- hash: 201983176826574058
150
+ hash: 2777108850332874749
150
151
  requirements: []
151
152
  rubyforge_project:
152
153
  rubygems_version: 1.8.25
@@ -158,6 +159,7 @@ test_files:
158
159
  - test/functional/_lib.rb
159
160
  - test/functional/_lib/scripts/core.rb
160
161
  - test/functional/configatron.rb
162
+ - test/functional/delayed.rb
161
163
  - test/functional/loading.rb
162
164
  - test/functional/minitest.rb
163
165
  - test/unit/_lib.rb