configurate 0.0.2 → 0.0.3

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: 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-----