configurate 0.0.2 → 0.0.3

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b50fb25fde4dc42ae6cdc150bb6042fea6c0cd09
4
+ data.tar.gz: 3a9b3988d4d030c58a14d58c116fdb6a3682629c
5
+ SHA512:
6
+ metadata.gz: b30760168a9e5da90281dd3756f661c05ef4db4f27a8cce9eb08c1d3fb3cf2ad609992af0685511ad027eb6398665a12c07b87f6e508e08cbe05643a740abcd5
7
+ data.tar.gz: 387ce8d7237c183a3b214b9308d5c3227dfef1dbeea7b1ff97c208bceae2888483f2efce0aae60190a49c81e64e27ed20da6897741ec69e82078cfe4454677da
checksums.yaml.gz.asc ADDED
@@ -0,0 +1,11 @@
1
+ -----BEGIN PGP SIGNATURE-----
2
+ Version: GnuPG v2.0.19 (GNU/Linux)
3
+
4
+ iQEcBAABAgAGBQJRaxYFAAoJEPNH4OtHrHDWk80H/jAcCNmTYyFrUrm6lK3kOlo3
5
+ SnhKm+xDqB/izEJD7EZMtCEPVeC4ArrNbrN10PJZ6mQgHApenBJ5CDXqFdlTIT0b
6
+ n+qFL+kcfK0abBrJz5g0Sv4wS5rCDWWYZLl4CiGLmbalQRB6fSsWiXFNlBVawt7l
7
+ 88ZGE8vL8eR/F0JycjiE6fjryvg8qplZiC7NzqkpSmN0hxzqc5leHY7JoYgAP4PN
8
+ cloCT0I3iUH+fCqez8ujX3NX2RdURVfL+bilLf4LROOlaAvZgYYjngWUOWFnv3AJ
9
+ e9+JXSgNme9zmuTA/DtD29r9CSHf0Sc7EO18vJrJTJ6a+Dv9Qe/2IwBYWkmibdo=
10
+ =rgFX
11
+ -----END PGP SIGNATURE-----
data.tar.gz.asc ADDED
@@ -0,0 +1,11 @@
1
+ -----BEGIN PGP SIGNATURE-----
2
+ Version: GnuPG v2.0.19 (GNU/Linux)
3
+
4
+ iQEcBAABAgAGBQJRaxYFAAoJEPNH4OtHrHDWpOIH/jkbHhYBNcCMizn4WTWWKvx+
5
+ rIUozwKicxON4uebRoP6RIuzKQzhSs1mYZbQebo4qY/EVAI2zU+ysuyhCJlsELZG
6
+ Au/Lh3xYCS7OIP3KGVCo8eblenEG0OjaeDIfe08TuoZumx9Hv39jmK6uRG9jvCBX
7
+ tEZmw1T2bDn2uDOaolUD7BiMZgXYigH4RIZcpsd7qb7nniyHH7ULET2ofSWQpK3a
8
+ GGHV6yZdtbgnpt3f4o3dFKF4+aEYmWZ/deJbCwsvA9rNIIDfQZzS91sNCQAPp7RK
9
+ y8ryytPhGb2hCUqgNLZpNg/cfSwgkU3PRmcq2q8FxHvu9qCxafgmSYq4LWy70tA=
10
+ =99eN
11
+ -----END PGP SIGNATURE-----
data/lib/configurate.rb CHANGED
@@ -1,4 +1,5 @@
1
1
 
2
+ require 'configurate/setting_path'
2
3
  require 'configurate/lookup_chain'
3
4
  require 'configurate/provider'
4
5
  require 'configurate/proxy'
@@ -6,12 +7,12 @@ require 'configurate/proxy'
6
7
 
7
8
  # A flexible and extendable configuration system.
8
9
  # The calling logic is isolated from the lookup logic
9
- # through configuration providers, which only requirement
10
+ # through configuration providers, whose only requirement
10
11
  # is to define the +#lookup+ method and show a certain behavior on that.
11
12
  # The providers are asked in the order they were added until one provides
12
13
  # a response. This allows to even add multiple providers of the same type,
13
14
  # you never easier defined your default configuration parameters.
14
- # There are no class methods used, you can have an unlimited amount of
15
+ # There is no shared state, you can have an unlimited amount of
15
16
  # independent configuration sources at the same time.
16
17
  #
17
18
  # See {Settings} for a quick start.
@@ -19,7 +20,7 @@ module Configurate
19
20
  # This is your main entry point. Instead of lengthy explanations
20
21
  # let an example demonstrate its usage:
21
22
  #
22
- # require Rails.root.join('lib', 'configuration')
23
+ # require 'configuration_methods'
23
24
  #
24
25
  # AppSettings = Configurate::Settings.create do
25
26
  # add_provider Configurate::Provider::Env
@@ -40,15 +41,19 @@ module Configurate
40
41
  undef_method :method # Remove possible conflicts with common setting names
41
42
 
42
43
  # @!method lookup(setting)
43
- # (see LookupChain#lookup)
44
+ # (see {LookupChain#lookup})
45
+
44
46
  # @!method add_provider(provider, *args)
45
- # (see LookupChain#add_provider)
47
+ # (see {LookupChain#add_provider})
48
+
46
49
  # @!method [](setting)
47
- # (see LookupChain#[])
50
+ # (see {LookupChain#[]})
51
+
52
+ # See description and {#lookup}, {#[]} and {#add_provider}
48
53
  def method_missing(method, *args, &block)
49
- return @lookup_chain.send(method, *args, &block) if [:lookup, :add_provider, :[]].include?(method)
54
+ return @lookup_chain.public_send(method, *args, &block) if [:lookup, :add_provider, :[]].include?(method)
50
55
 
51
- Proxy.new(@lookup_chain).send(method, *args, &block)
56
+ Proxy.new(@lookup_chain).public_send(method, *args, &block)
52
57
  end
53
58
 
54
59
  def initialize
@@ -1,12 +1,12 @@
1
1
  module Configurate
2
2
  # This object builds a chain of configuration providers to try to find
3
- # a setting.
3
+ # the value of a setting.
4
4
  class LookupChain
5
5
  def initialize
6
6
  @provider = []
7
7
  end
8
8
 
9
- # Add a provider to the chain. Providers are tried in the order
9
+ # Adds a provider to the chain. Providers are tried in the order
10
10
  # they are added, so the order is important.
11
11
  #
12
12
  # @param provider [#lookup]
@@ -25,14 +25,13 @@ module Configurate
25
25
  # Tries all providers in the order they were added to provide a response
26
26
  # for setting.
27
27
  #
28
- # @param setting [#to_s] settings should be underscore_case,
29
- # nested settings should be separated by a dot
30
- # @param *args further args passed to the provider
31
- # @return [Array,String,Boolean,nil] whatever the provider provides
32
- # is casted to a {String}, except for some special values
28
+ # @param setting [SettingPath,String] nested settings as strings should
29
+ # be separated by a dot
30
+ # @param ... further args passed to the provider
31
+ # @return [Array,Hash,String,Boolean,nil] whatever the responding
32
+ # provider provides is casted to a {String}, except for some special values
33
33
  def lookup(setting, *args)
34
- setting = setting.to_s
35
-
34
+ setting = SettingPath.from_string(setting) if setting.is_a? String
36
35
  @provider.each do |provider|
37
36
  begin
38
37
  return special_value_or_string(provider.lookup(setting, *args))
@@ -1,15 +1,14 @@
1
1
  module Configurate; module Provider
2
2
  # This provides a basic {#lookup} method for other providers to build
3
- # upon. Childs are expected to define +lookup_path(path, *args)+ where
4
- # +path+ will be passed an array of settings generated by splitting the
5
- # called setting at the dots. The method should return nil if the setting
3
+ # upon. Childs are expected to define +lookup_path(path, *args)+.
4
+ # The method should return nil if the setting
6
5
  # wasn't found and {#lookup} will raise an {SettingNotFoundError} in that
7
6
  # case.
8
7
  class Base
9
- def lookup(setting, *args)
10
- result = lookup_path(setting.split("."), *args)
8
+ def lookup(*args)
9
+ result = lookup_path(*args)
11
10
  return result unless result.nil?
12
- raise Configurate::SettingNotFoundError, "The setting #{setting} was not found"
11
+ raise Configurate::SettingNotFoundError, "The setting #{args.first} was not found"
13
12
  end
14
13
  end
15
14
  end; end
@@ -8,11 +8,10 @@ module Configurate; module Provider
8
8
  @settings = {}
9
9
  end
10
10
 
11
- def lookup_path(settings_path, *args)
12
- key = settings_path.join(".")
11
+ def lookup_path(setting_path, *args)
12
+ key = setting_path.to_s
13
13
 
14
- if key.end_with?("=") && args.length > 0
15
- key = key.chomp("=")
14
+ if setting_path.is_setter? && args.length > 0
16
15
  value = args.first
17
16
  value = value.get if value.respond_to?(:_proxy?) && value._proxy?
18
17
  @settings[key] = value
@@ -1,14 +1,16 @@
1
1
  module Configurate; module Provider
2
2
  # This provider looks for settings in the environment.
3
3
  # For the setting +foo.bar_baz+ this provider will look for an
4
- # environment variable +FOO_BAR_BAZ+, replacing all dots in the setting
5
- # and upcasing the result. If an value contains +,+ it's split at them
6
- # and returned as array.
4
+ # environment variable +FOO_BAR_BAZ+, joining all components of the
5
+ # setting with underscores and upcasing the result.
6
+ # If an value contains any commas (,) it's split at them and returned as array.
7
7
  class Env < Base
8
- def lookup_path(settings_path, *args)
9
- value = ENV[settings_path.join("_").upcase]
10
- value = value.dup unless value.nil?
11
- value = value.split(",") if value && value.include?(",")
8
+ def lookup_path(setting_path, *args)
9
+ value = ENV[setting_path.join("_").upcase]
10
+ unless value.nil?
11
+ value = value.dup
12
+ value = value.split(",") if value.include?(",")
13
+ end
12
14
  value
13
15
  end
14
16
  end
@@ -1,7 +1,7 @@
1
1
  require 'yaml'
2
2
 
3
3
  module Configurate; module Provider
4
- # This provider tries to open a YAML file and does in nested lookups
4
+ # This provider tries to open a YAML file and does nested lookups
5
5
  # in it.
6
6
  class YAML < Base
7
7
  # @param file [String] the path to the file
@@ -13,27 +13,30 @@ module Configurate; module Provider
13
13
  # @raise [Errno:ENOENT] if the file isn't found
14
14
  def initialize(file, opts = {})
15
15
  @settings = {}
16
- required = opts.has_key?(:required) ? opts.delete(:required) : true
16
+ required = opts.delete(:required) { true }
17
17
 
18
18
  @settings = ::YAML.load_file(file)
19
19
 
20
20
  namespace = opts.delete(:namespace)
21
21
  unless namespace.nil?
22
- actual_settings = lookup_in_hash(namespace.split("."), @settings)
23
- unless actual_settings.nil?
22
+ namespace = SettingPath.from_string(namespace)
23
+ actual_settings = lookup_in_hash(namespace, @settings)
24
+ if !actual_settings.nil?
24
25
  @settings = actual_settings
26
+ elsif required
27
+ raise ArgumentError, "Namespace #{namespace} not found in #{file}"
25
28
  else
26
- raise ArgumentError, "Namespace #{namespace} not found in #{file}" if required
29
+ $stderr.puts "WARNING: Namespace #{namespace} not found in #{file}"
27
30
  end
28
31
  end
29
32
  rescue Errno::ENOENT => e
30
- $stderr.puts "WARNING: configuration file #{file} not found, ensure it's present"
33
+ $stderr.puts "WARNING: Configuration file #{file} not found, ensure it's present"
31
34
  raise e if required
32
35
  end
33
36
 
34
37
 
35
- def lookup_path(settings_path, *args)
36
- lookup_in_hash(settings_path, @settings)
38
+ def lookup_path(setting_path, *args)
39
+ lookup_in_hash(setting_path, @settings)
37
40
  end
38
41
 
39
42
  private
@@ -42,7 +45,7 @@ module Configurate; module Provider
42
45
  setting = setting_path.shift
43
46
  if hash.has_key?(setting)
44
47
  if setting_path.length > 0 && hash[setting].is_a?(Hash)
45
- return lookup_in_hash(setting_path, hash[setting]) if setting.length > 1
48
+ return lookup_in_hash(setting_path, hash[setting]) if setting.length >= 1
46
49
  else
47
50
  return hash[setting]
48
51
  end
@@ -1,32 +1,34 @@
1
1
  module Configurate
2
2
  # Proxy object to support nested settings
3
- # Cavehat: Since this is always true, adding a ? at the end
3
+ #
4
+ # *Cavehats*: Since this object is always true, adding a +?+ at the end
4
5
  # returns the value, if found, instead of the proxy object.
5
6
  # So instead of +if settings.foo.bar+ use +if settings.foo.bar?+
6
7
  # to check for boolean values, +if settings.foo.bar.nil?+ to
7
- # check for nil values, +if settings.foo.bar.present?+ to check for
8
- # empty values if you're in Rails and call {#get} to actually return the value,
9
- # commonly when doing +settings.foo.bar.get || 'default'+. If a setting
10
- # ends with +=+ is too called directly, just like with +?+.
8
+ # check for nil values and of course you can do +if settings.foo.bar.present?+ to check for
9
+ # empty values if you're in Rails. Call {#get} to actually return the value,
10
+ # commonly when doing +settings.foo.bar.get || "default"+. Also don't
11
+ # use this in case statements since +Module#===+ can't be fooled, again
12
+ # call {#get}.
13
+ #
14
+ # If a setting ends with +=+ it's too called directly, just like with +?+.
11
15
  class Proxy < BasicObject
12
- COMMON_KEY_NAMES = [:key, :method]
13
-
14
16
  # @param lookup_chain [#lookup]
15
17
  def initialize(lookup_chain)
16
18
  @lookup_chain = lookup_chain
17
- @setting = ""
19
+ @setting_path = SettingPath.new
18
20
  end
19
21
 
20
22
  def !
21
- !self.get
23
+ !target
22
24
  end
23
25
 
24
26
  def !=(other)
25
- self.get != other
27
+ target != other
26
28
  end
27
29
 
28
30
  def ==(other)
29
- self.get == other
31
+ target == other
30
32
  end
31
33
 
32
34
  def _proxy?
@@ -34,43 +36,43 @@ module Configurate
34
36
  end
35
37
 
36
38
  def respond_to?(method, include_private=false)
37
- method == :_proxy? || self.get.respond_to?(method, include_private)
39
+ method == :_proxy? || target.respond_to?(method, include_private)
38
40
  end
39
41
 
40
42
  def send(*args, &block)
41
- self.__send__(*args, &block)
43
+ __send__(*args, &block)
42
44
  end
45
+ alias_method :public_send, :send
43
46
 
44
47
  def method_missing(setting, *args, &block)
45
- unless COMMON_KEY_NAMES.include? setting
46
- target = self.get
47
- if !(target.respond_to?(:_proxy?) && target._proxy?) && target.respond_to?(setting)
48
- return target.send(setting, *args, &block)
49
- end
50
- end
48
+ return target.public_send(setting, *args, &block) if target_respond_to? setting
51
49
 
52
- setting = setting.to_s
53
-
54
- self.append_setting(setting)
50
+ @setting_path << setting
55
51
 
56
- return self.get(*args) if setting.end_with?("?") || setting.end_with?("=")
52
+ return target(*args) if @setting_path.is_question_or_setter?
57
53
 
58
54
  self
59
55
  end
60
56
 
61
57
  # Get the setting at the current path, if found.
62
58
  # (see LookupChain#lookup)
63
- def get(*args)
64
- setting = @setting[1..-1]
65
- return unless setting
66
- val = @lookup_chain.lookup(setting.chomp("?"), *args)
67
- val
59
+ def target(*args)
60
+ return if @setting_path.empty?
61
+
62
+ @lookup_chain.lookup(@setting_path, *args)
68
63
  end
64
+ alias_method :get, :target
69
65
 
70
- protected
71
- def append_setting(setting)
72
- @setting << "."
73
- @setting << setting
66
+ private
67
+ COMMON_KEY_NAMES = [:key, :method]
68
+
69
+ def target_respond_to?(setting)
70
+ return false if COMMON_KEY_NAMES.include? setting
71
+
72
+ value = target
73
+ return false if value.respond_to?(:_proxy?) && value._proxy?
74
+
75
+ value.respond_to?(setting)
74
76
  end
75
77
  end
76
78
  end
@@ -0,0 +1,30 @@
1
+ module Configurate
2
+ # Class encapsulating the concept of a path to a setting
3
+ class SettingPath < Array
4
+
5
+ # Create a path from the string format (+foo.bar+).
6
+ # @param path [String]
7
+ # @return [SettingPath]
8
+ def self.from_string(path)
9
+ SettingPath.new(path.split("."))
10
+ end
11
+
12
+ # Whether the current path looks like a question or setter method
13
+ def is_question_or_setter?
14
+ last.to_s.end_with?("?") || is_setter?
15
+ end
16
+
17
+ # Whether the current path looks like a setter method
18
+ def is_setter?
19
+ last.to_s.end_with?("=")
20
+ end
21
+
22
+ def to_s
23
+ join(".").chomp("?").chomp("=")
24
+ end
25
+
26
+ def inspect
27
+ "<SettingPath path=#{to_s}>"
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,84 @@
1
+ require 'spec_helper'
2
+
3
+ class InvalidConfigurationProvider; end
4
+ class ValidConfigurationProvider
5
+ def lookup(setting, *args); end
6
+ end
7
+
8
+ describe Configurate::LookupChain do
9
+ subject { described_class.new }
10
+
11
+ describe "#add_provider" do
12
+ it "adds a valid provider" do
13
+ expect {
14
+ subject.add_provider ValidConfigurationProvider
15
+ }.to change { subject.instance_variable_get(:@provider).size }.by 1
16
+ end
17
+
18
+ it "doesn't add an invalid provider" do
19
+ expect {
20
+ subject.add_provider InvalidConfigurationProvider
21
+ }.to raise_error ArgumentError
22
+ end
23
+
24
+ it "passes extra args to the provider" do
25
+ ValidConfigurationProvider.should_receive(:new).with(:extra)
26
+ subject.add_provider ValidConfigurationProvider, :extra
27
+ end
28
+ end
29
+
30
+ describe "#lookup" do
31
+ before do
32
+ subject.add_provider ValidConfigurationProvider
33
+ subject.add_provider ValidConfigurationProvider
34
+ @provider = subject.instance_variable_get(:@provider)
35
+ end
36
+
37
+ it "it tries all providers" do
38
+ setting = Configurate::SettingPath.from_string "some.setting"
39
+ @provider.each do |provider|
40
+ provider.should_receive(:lookup).with(setting).and_raise(Configurate::SettingNotFoundError)
41
+ end
42
+
43
+ subject.lookup(setting)
44
+ end
45
+
46
+ it "stops if a value is found" do
47
+ @provider[0].should_receive(:lookup).and_return("something")
48
+ @provider[1].should_not_receive(:lookup)
49
+ subject.lookup("bla")
50
+ end
51
+
52
+ it "converts numbers to strings" do
53
+ @provider[0].stub(:lookup).and_return(5)
54
+ subject.lookup("foo").should == "5"
55
+ end
56
+
57
+ it "does not convert false to a string" do
58
+ @provider[0].stub(:lookup).and_return(false)
59
+ subject.lookup("enable").should be_false
60
+ end
61
+
62
+ it "converts 'true' to true" do
63
+ @provider[0].stub(:lookup).and_return("true")
64
+ subject.lookup("enable").should be_true
65
+ end
66
+
67
+ it "converts 'false' to false" do
68
+ @provider[0].stub(:lookup).and_return("false")
69
+ subject.lookup("enable").should be_false
70
+ end
71
+
72
+ it "returns the value unchanged if it can't be converted" do
73
+ value = mock
74
+ value.stub(:respond_to?).with(:to_s).and_return(false)
75
+ @provider[0].stub(:lookup).and_return(value)
76
+ subject.lookup("enable").should == value
77
+ end
78
+
79
+ it "returns nil if no value is found" do
80
+ @provider.each { |p| p.stub(:lookup).and_raise(Configurate::SettingNotFoundError) }
81
+ subject.lookup("not.me").should be_nil
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe Configurate::Provider::Dynamic do
4
+ subject { described_class.new }
5
+ describe "#lookup_path" do
6
+ it "returns nil if the setting was never set" do
7
+ subject.lookup_path(Configurate::SettingPath.new(["not_me"])).should be_nil
8
+ end
9
+
10
+ it "remembers the setting if it ends with =" do
11
+ subject.lookup_path(Configurate::SettingPath.new(["find_me", "later="]), "there")
12
+ subject.lookup_path(Configurate::SettingPath.new(["find_me", "later"])).should == "there"
13
+ end
14
+
15
+ it "calls .get on the argument if a proxy object is given" do
16
+ proxy = mock
17
+ proxy.stub(:respond_to?).and_return(true)
18
+ proxy.stub(:_proxy?).and_return(true)
19
+ proxy.should_receive(:get)
20
+ subject.lookup_path(Configurate::SettingPath.new(["bla="]), proxy)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe Configurate::Provider::Env do
4
+ subject { described_class.new }
5
+ let(:existing_path) { ['existing', 'setting']}
6
+ let(:not_existing_path) { ['not', 'existing', 'path']}
7
+ let(:array_path) { ['array'] }
8
+ before(:all) do
9
+ ENV['EXISTING_SETTING'] = "there"
10
+ ENV['ARRAY'] = "foo,bar,baz"
11
+ end
12
+
13
+ after(:all) do
14
+ ENV['EXISTING_SETTING'] = nil
15
+ ENV['ARRAY'] = nil
16
+ end
17
+
18
+ describe '#lookup_path' do
19
+ it "joins and upcases the path" do
20
+ ENV.should_receive(:[]).with("EXISTING_SETTING")
21
+ subject.lookup_path(existing_path)
22
+ end
23
+
24
+ it "returns nil if the setting isn't available" do
25
+ subject.lookup_path(not_existing_path).should be_nil
26
+ end
27
+
28
+ it "makes an array out of comma separated values" do
29
+ subject.lookup_path(array_path).should == ["foo", "bar", "baz"]
30
+ end
31
+
32
+ it "returns a unfrozen string" do
33
+ expect {
34
+ setting = subject.lookup_path(existing_path)
35
+ setting << "foo"
36
+ }.to_not raise_error
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,72 @@
1
+ require 'spec_helper'
2
+
3
+ describe Configurate::Provider::YAML do
4
+ let(:settings) { {"toplevel" => "bar",
5
+ "some" => {
6
+ "nested" => { "some" => "lala", "setting" => "foo"}
7
+ }
8
+ } }
9
+
10
+ describe "#initialize" do
11
+ it "loads the file" do
12
+ file = "foobar.yml"
13
+ ::YAML.should_receive(:load_file).with(file).and_return({})
14
+ described_class.new file
15
+ end
16
+
17
+ it "raises if the file is not found" do
18
+ ::YAML.stub(:load_file).and_raise(Errno::ENOENT)
19
+ expect {
20
+ described_class.new "foo"
21
+ }.to raise_error Errno::ENOENT
22
+ end
23
+
24
+
25
+ context "with a namespace" do
26
+ it "looks in the file for that namespace" do
27
+ namespace = "some"
28
+ ::YAML.stub(:load_file).and_return(settings)
29
+ provider = described_class.new 'bla', namespace: namespace
30
+ provider.instance_variable_get(:@settings).should == settings[namespace]
31
+ end
32
+
33
+ it "raises if the namespace isn't found" do
34
+ ::YAML.stub(:load_file).and_return({})
35
+ expect {
36
+ described_class.new 'bla', namespace: "foo"
37
+ }.to raise_error ArgumentError
38
+ end
39
+ end
40
+
41
+ context "with required set to false" do
42
+ it "doesn't raise if a file isn't found" do
43
+ ::YAML.stub(:load_file).and_raise(Errno::ENOENT)
44
+ expect {
45
+ described_class.new "not_me", required: false
46
+ }.not_to raise_error Errno::ENOENT
47
+ end
48
+
49
+ it "doesn't raise if a namespace isn't found" do
50
+ ::YAML.stub(:load_file).and_return({})
51
+ expect {
52
+ described_class.new 'bla', namespace: "foo", required: false
53
+ }.not_to raise_error ArgumentError
54
+ end
55
+ end
56
+ end
57
+
58
+ describe "#lookup_path" do
59
+ before do
60
+ ::YAML.stub(:load_file).and_return(settings)
61
+ @provider = described_class.new 'dummy'
62
+ end
63
+
64
+ it "looks up the whole nesting" do
65
+ @provider.lookup_path(["some", "nested", "some"]).should == settings["some"]["nested"]["some"]
66
+ end
67
+
68
+ it "returns nil if no setting is found" do
69
+ @provider.lookup_path(["not_me"]).should be_nil
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe Configurate::Provider::Base do
4
+ describe "#lookup" do
5
+ subject { described_class.new }
6
+ it "calls #lookup_path" do
7
+ path = Configurate::SettingPath.new(["foo", "bar"])
8
+ subject.should_receive(:lookup_path).with(path).and_return("something")
9
+ subject.lookup(path).should == "something"
10
+ end
11
+
12
+ it "raises SettingNotFoundError if the #lookup_path returns nil" do
13
+ subject.stub(:lookup_path).and_return(nil)
14
+ expect {
15
+ subject.lookup("bla")
16
+ }.to raise_error Configurate::SettingNotFoundError
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,78 @@
1
+ require 'spec_helper'
2
+
3
+ describe Configurate::Proxy do
4
+ let(:lookup_chain) { mock(lookup: "something") }
5
+ let(:proxy) { described_class.new(lookup_chain) }
6
+
7
+ describe "in case statements" do
8
+ it "acts like the target" do
9
+ pending "If anyone knows a way to overwrite ===, please tell me :P"
10
+ result = case proxy
11
+ when String
12
+ "string"
13
+ else
14
+ "wrong"
15
+ end
16
+ result.should == "string"
17
+ end
18
+ end
19
+
20
+ describe "#method_missing" do
21
+ it "calls #target if the method ends with a ?" do
22
+ lookup_chain.should_receive(:lookup).and_return(false)
23
+ proxy.method_missing(:enable?)
24
+ end
25
+
26
+ it "calls #target if the method ends with a =" do
27
+ lookup_chain.should_receive(:lookup).and_return(false)
28
+ proxy.method_missing(:url=)
29
+ end
30
+ end
31
+
32
+ describe "delegations" do
33
+ it "calls the target when negating" do
34
+ target = mock
35
+ lookup_chain.stub(:lookup).and_return(target)
36
+ target.should_receive(:!)
37
+ proxy.something.__send__(:!)
38
+ end
39
+
40
+ it "calls __send__ on send" do
41
+ proxy.should_receive(:__send__).with(:foo).and_return(nil)
42
+ proxy.send(:foo)
43
+ end
44
+ end
45
+
46
+ describe "#proxy" do
47
+ subject { proxy._proxy? }
48
+ it { should be_true }
49
+ end
50
+
51
+ describe "#target" do
52
+ [:to_str, :to_s, :to_xml, :respond_to?, :present?, :!=,
53
+ :each, :try, :size, :length, :count, :==, :=~, :gsub, :blank?, :chop,
54
+ :start_with?, :end_with?].each do |method|
55
+ it "is called for accessing #{method} on the proxy" do
56
+ target = mock
57
+ lookup_chain.stub(:lookup).and_return(target)
58
+ target.stub(:respond_to?).and_return(true)
59
+ target.stub(:_proxy?).and_return(false)
60
+ target.should_receive(method).and_return("something")
61
+ proxy.something.__send__(method, mock)
62
+ end
63
+ end
64
+
65
+ described_class::COMMON_KEY_NAMES.each do |method|
66
+ it "is not called for accessing #{method} on the proxy" do
67
+ target = mock
68
+ lookup_chain.should_not_receive(:lookup)
69
+ target.should_not_receive(method)
70
+ proxy.something.__send__(method, mock)
71
+ end
72
+ end
73
+
74
+ it "returns nil if no setting is given" do
75
+ proxy.target.should be_nil
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ describe Configurate::SettingPath do
4
+ describe "::from_string" do
5
+ it "creates a path" do
6
+ described_class.from_string("foo.bar").should == described_class.new(["foo", "bar"])
7
+ end
8
+ end
9
+
10
+ describe "#is_setter?" do
11
+ context "with a setter signature as setting" do
12
+ subject { described_class.new([:foo=]).is_setter? }
13
+ it { should be_true }
14
+ end
15
+
16
+ context "with a normal path as setting" do
17
+ subject { described_class.new([:foo]).is_setter? }
18
+ it { should be_false }
19
+ end
20
+ end
21
+
22
+
23
+ describe "#is_question_or_setter?" do
24
+ context "with a question signature as setting" do
25
+ subject { described_class.new([:foo?]).is_question_or_setter? }
26
+ it { should be_true }
27
+ end
28
+
29
+ context "with a setter signature as setting" do
30
+ subject { described_class.new([:foo=]).is_question_or_setter? }
31
+ it { should be_true }
32
+ end
33
+
34
+ context "with a normal path as setting" do
35
+ subject { described_class.new([:foo]).is_question_or_setter? }
36
+ it { should be_false }
37
+ end
38
+ end
39
+
40
+ describe "#to_s" do
41
+ let(:path) { "example.path" }
42
+ subject { described_class.new(path.split(".")).to_s }
43
+ it { should == path }
44
+
45
+ context "with a question signature as setting" do
46
+ subject { described_class.new("#{path}?".split(".")).to_s }
47
+ it { should == path }
48
+ end
49
+ end
50
+
51
+ describe "#inspect" do
52
+ it "includes the dotted path" do
53
+ path = described_class.new([:foo, :bar])
54
+ path.inspect.should include "foo.bar"
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe Configurate::Settings do
4
+ describe "#method_missing" do
5
+ subject { described_class.create }
6
+
7
+ it "delegates the call to a new proxy object" do
8
+ proxy = mock
9
+ Configurate::Proxy.should_receive(:new).and_return(proxy)
10
+ proxy.should_receive(:method_missing).with(:some_setting).and_return("foo")
11
+ subject.some_setting
12
+ end
13
+ end
14
+
15
+ [:lookup, :add_provider, :[]].each do |method|
16
+ describe "#{method}" do
17
+ subject { described_class.create }
18
+
19
+ it "delegates the call to #lookup_chain" do
20
+ subject.lookup_chain.should_receive(method)
21
+ subject.send(method)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,26 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+
8
+
9
+ begin
10
+ require 'coveralls'
11
+ Coveralls.wear!
12
+ rescue; end
13
+
14
+ require 'configurate'
15
+
16
+ RSpec.configure do |config|
17
+ config.treat_symbols_as_metadata_keys_with_true_values = true
18
+ config.run_all_when_everything_filtered = true
19
+ config.filter_run :focus
20
+
21
+ # Run specs in random order to surface order dependencies. If you find an
22
+ # order dependency and want to debug it, you can fix the order by providing
23
+ # the seed, which is printed after each run.
24
+ # --seed 1234
25
+ config.order = 'random'
26
+ end
metadata CHANGED
@@ -1,16 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: configurate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
5
- prerelease:
4
+ version: 0.0.3
6
5
  platform: ruby
7
6
  authors:
8
7
  - Jonne Haß
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-01-29 00:00:00.000000000 Z
13
- dependencies: []
11
+ date: 2013-04-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 10.0.3
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: 10.0.3
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: 2.12.0
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: 2.12.0
14
41
  description: Configurate is a flexible configuration system that can read settings
15
42
  from multiple sources at the same time.
16
43
  email: me@mrzyx.de
@@ -24,30 +51,49 @@ files:
24
51
  - lib/configurate/proxy.rb
25
52
  - lib/configurate/lookup_chain.rb
26
53
  - lib/configurate/provider.rb
54
+ - lib/configurate/setting_path.rb
27
55
  - lib/configurate.rb
28
- homepage: https://github.com/MrZYX/configurate
56
+ - spec/configurate/provider_spec.rb
57
+ - spec/configurate/lookup_chain_spec.rb
58
+ - spec/configurate/provider/yaml_spec.rb
59
+ - spec/configurate/provider/env_spec.rb
60
+ - spec/configurate/provider/dynamic_spec.rb
61
+ - spec/configurate/setting_path_spec.rb
62
+ - spec/configurate/proxy_spec.rb
63
+ - spec/spec_helper.rb
64
+ - spec/configurate_spec.rb
65
+ homepage: http://mrzyx.github.com/configurate
29
66
  licenses:
30
67
  - MIT
68
+ metadata: {}
31
69
  post_install_message:
32
70
  rdoc_options: []
33
71
  require_paths:
34
72
  - lib
35
73
  required_ruby_version: !ruby/object:Gem::Requirement
36
- none: false
37
74
  requirements:
38
- - - ~>
75
+ - - '>='
39
76
  - !ruby/object:Gem::Version
40
77
  version: 1.9.2
41
78
  required_rubygems_version: !ruby/object:Gem::Requirement
42
- none: false
43
79
  requirements:
44
- - - ! '>='
80
+ - - '>='
45
81
  - !ruby/object:Gem::Version
46
82
  version: '0'
47
83
  requirements: []
48
84
  rubyforge_project:
49
- rubygems_version: 1.8.24
85
+ rubygems_version: 2.0.3
50
86
  signing_key:
51
- specification_version: 3
87
+ specification_version: 4
52
88
  summary: Flexbile configuration system
53
- test_files: []
89
+ test_files:
90
+ - spec/configurate/provider_spec.rb
91
+ - spec/configurate/lookup_chain_spec.rb
92
+ - spec/configurate/provider/yaml_spec.rb
93
+ - spec/configurate/provider/env_spec.rb
94
+ - spec/configurate/provider/dynamic_spec.rb
95
+ - spec/configurate/setting_path_spec.rb
96
+ - spec/configurate/proxy_spec.rb
97
+ - spec/spec_helper.rb
98
+ - spec/configurate_spec.rb
99
+ has_rdoc:
metadata.gz.asc ADDED
@@ -0,0 +1,11 @@
1
+ -----BEGIN PGP SIGNATURE-----
2
+ Version: GnuPG v2.0.19 (GNU/Linux)
3
+
4
+ iQEcBAABAgAGBQJRaxYFAAoJEPNH4OtHrHDW48EIAKYLXtBlFZNnezvqLJr7aQYt
5
+ 6HGva0USAoso1Rvn7t3HV4BIR7rFhscOUMMWwddHElNMnLxzsQU1vLQ0Zzk7+bGZ
6
+ pR2irAuTjEJHZUCifVwSmIGK5CbyHbwqDhFOhexQOh8cPxYWo3IcHT/Pq7H3graS
7
+ /POfxD1kUClc/l/NMV0OdCCXjdDisbVP+j2Ju6pNQU8QPk7QOjKDlmx7WTmlP3c7
8
+ RA+gzCqxpYw2+F6XHCFoQRAdb8KYLOkn2YGUmGzcpbh19qniEMTVcum4YhWqvG+S
9
+ 3igR/0DX219J0332XhbqlcLzfcB+EeGHrRKlY1LGm8JeHA9MR6JNGpoROSPP2TY=
10
+ =0vyr
11
+ -----END PGP SIGNATURE-----