extract configruation system to a gem
This commit is contained in:
parent
656e52360f
commit
669dd87b11
20 changed files with 17 additions and 624 deletions
|
|
@ -5,6 +5,7 @@
|
||||||
* Removed unused stuff [#3714](https://github.com/diaspora/diaspora/pull/3714), [#3754](https://github.com/diaspora/diaspora/pull/3754)
|
* Removed unused stuff [#3714](https://github.com/diaspora/diaspora/pull/3714), [#3754](https://github.com/diaspora/diaspora/pull/3754)
|
||||||
* Last post link isn't displayed anymore if there are no visible posts [#3750](https://github.com/diaspora/diaspora/issues/3750)
|
* Last post link isn't displayed anymore if there are no visible posts [#3750](https://github.com/diaspora/diaspora/issues/3750)
|
||||||
* Ported tag followings to backbone [#3713](https://github.com/diaspora/diaspora/pull/3713)
|
* Ported tag followings to backbone [#3713](https://github.com/diaspora/diaspora/pull/3713)
|
||||||
|
* Extracted configuration system to a gem.
|
||||||
|
|
||||||
## Bug Fixes
|
## Bug Fixes
|
||||||
|
|
||||||
|
|
|
||||||
3
Gemfile
3
Gemfile
|
|
@ -8,6 +8,9 @@ gem 'unicorn', '4.4.0', :require => false
|
||||||
|
|
||||||
gem 'rails_autolink', '1.0.9'
|
gem 'rails_autolink', '1.0.9'
|
||||||
|
|
||||||
|
# configuration
|
||||||
|
gem 'configurate', '0.0.1'
|
||||||
|
|
||||||
# cross-origin resource sharing
|
# cross-origin resource sharing
|
||||||
|
|
||||||
gem 'rack-cors', '0.2.7', :require => 'rack/cors'
|
gem 'rack-cors', '0.2.7', :require => 'rack/cors'
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,7 @@ GEM
|
||||||
execjs
|
execjs
|
||||||
coffee-script-source (1.4.0)
|
coffee-script-source (1.4.0)
|
||||||
columnize (0.3.6)
|
columnize (0.3.6)
|
||||||
|
configurate (0.0.1)
|
||||||
crack (0.3.1)
|
crack (0.3.1)
|
||||||
cucumber (1.2.1)
|
cucumber (1.2.1)
|
||||||
builder (>= 2.1.2)
|
builder (>= 2.1.2)
|
||||||
|
|
@ -430,6 +431,7 @@ DEPENDENCIES
|
||||||
capybara (= 1.1.3)
|
capybara (= 1.1.3)
|
||||||
carrierwave (= 0.7.1)
|
carrierwave (= 0.7.1)
|
||||||
client_side_validations (= 3.2.1)
|
client_side_validations (= 3.2.1)
|
||||||
|
configurate (= 0.0.1)
|
||||||
cucumber-rails (= 1.3.0)
|
cucumber-rails (= 1.3.0)
|
||||||
database_cleaner (= 0.9.1)
|
database_cleaner (= 0.9.1)
|
||||||
debugger (= 1.2.1)
|
debugger (= 1.2.1)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
require Rails.root.join('lib', 'configuration')
|
require Rails.root.join('lib', 'configuration_methods')
|
||||||
require Rails.root.join('lib', 'configuration', 'methods')
|
|
||||||
|
|
||||||
config_dir = Rails.root.join("config")
|
config_dir = Rails.root.join("config")
|
||||||
|
|
||||||
|
|
@ -9,9 +8,9 @@ if File.exists?(config_dir.join("application.yml"))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
AppConfig ||= Configuration::Settings.create do
|
AppConfig ||= Configurate::Settings.create do
|
||||||
add_provider Configuration::Provider::Dynamic
|
add_provider Configurate::Provider::Dynamic
|
||||||
add_provider Configuration::Provider::Env
|
add_provider Configurate::Provider::Env
|
||||||
|
|
||||||
unless heroku? || Rails.env == "test" || File.exists?(config_dir.join("diaspora.yml"))
|
unless heroku? || Rails.env == "test" || File.exists?(config_dir.join("diaspora.yml"))
|
||||||
$stderr.puts "FATAL: Configuration not found. Copy over diaspora.yml.example"
|
$stderr.puts "FATAL: Configuration not found. Copy over diaspora.yml.example"
|
||||||
|
|
@ -19,16 +18,16 @@ AppConfig ||= Configuration::Settings.create do
|
||||||
Process.exit(1)
|
Process.exit(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
add_provider Configuration::Provider::YAML,
|
add_provider Configurate::Provider::YAML,
|
||||||
config_dir.join("diaspora.yml"),
|
config_dir.join("diaspora.yml"),
|
||||||
namespace: Rails.env, required: false
|
namespace: Rails.env, required: false
|
||||||
add_provider Configuration::Provider::YAML,
|
add_provider Configurate::Provider::YAML,
|
||||||
config_dir.join("diaspora.yml"),
|
config_dir.join("diaspora.yml"),
|
||||||
namespace: "configuration", required: false
|
namespace: "configuration", required: false
|
||||||
add_provider Configuration::Provider::YAML,
|
add_provider Configurate::Provider::YAML,
|
||||||
config_dir.join("defaults.yml"),
|
config_dir.join("defaults.yml"),
|
||||||
namespace: Rails.env
|
namespace: Rails.env
|
||||||
add_provider Configuration::Provider::YAML,
|
add_provider Configurate::Provider::YAML,
|
||||||
config_dir.join("defaults.yml"),
|
config_dir.join("defaults.yml"),
|
||||||
namespace: "defaults"
|
namespace: "defaults"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
||||||
|
|
||||||
require Rails.root.join('lib', 'configuration', 'lookup_chain')
|
|
||||||
require Rails.root.join('lib', 'configuration', 'provider')
|
|
||||||
require Rails.root.join('lib', 'configuration', 'proxy')
|
|
||||||
|
|
||||||
|
|
||||||
# A flexible and extendable configuration system.
|
|
||||||
# The calling logic is isolated from the lookup logic
|
|
||||||
# through configuration providers, which only requirement
|
|
||||||
# is to define the +#lookup+ method and show a certain behavior on that.
|
|
||||||
# The providers are asked in the order they were added until one provides
|
|
||||||
# a response. This allows to even add multiple providers of the same type,
|
|
||||||
# you never easier defined your default configuration parameters.
|
|
||||||
# There are no class methods used, you can have an unlimited amount of
|
|
||||||
# independent configuration sources at the same time.
|
|
||||||
#
|
|
||||||
# See {Settings} for a quick start.
|
|
||||||
module Configuration
|
|
||||||
# This is your main entry point. Instead of lengthy explanations
|
|
||||||
# let an example demonstrate its usage:
|
|
||||||
#
|
|
||||||
# require Rails.root.join('lib', 'configuration')
|
|
||||||
#
|
|
||||||
# AppSettings = Configuration::Settings.create do
|
|
||||||
# add_provider Configuration::Provider::Env
|
|
||||||
# add_provider Configuration::Provider::YAML, '/etc/app_settings.yml',
|
|
||||||
# namespace: Rails.env, required: false
|
|
||||||
# add_provider Configuration::Provider::YAML, 'config/default_settings.yml'
|
|
||||||
#
|
|
||||||
# extend YourConfigurationMethods
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# AppSettings.setup_something if AppSettings.something.enable?
|
|
||||||
#
|
|
||||||
# Please also read the note at {Proxy}!
|
|
||||||
class Settings
|
|
||||||
|
|
||||||
attr_reader :lookup_chain
|
|
||||||
|
|
||||||
undef_method :method # Remove possible conflicts with common setting names
|
|
||||||
|
|
||||||
# @!method lookup(setting)
|
|
||||||
# (see LookupChain#lookup)
|
|
||||||
# @!method add_provider(provider, *args)
|
|
||||||
# (see LookupChain#add_provider)
|
|
||||||
# @!method [](setting)
|
|
||||||
# (see LookupChain#[])
|
|
||||||
def method_missing(method, *args, &block)
|
|
||||||
return @lookup_chain.send(method, *args, &block) if [:lookup, :add_provider, :[]].include?(method)
|
|
||||||
|
|
||||||
Proxy.new(@lookup_chain).send(method, *args, &block)
|
|
||||||
end
|
|
||||||
|
|
||||||
def initialize
|
|
||||||
@lookup_chain = LookupChain.new
|
|
||||||
$stderr.puts "Warning you called Configuration::Settings.new with a block, you really meant to call #create" if block_given?
|
|
||||||
end
|
|
||||||
|
|
||||||
# Create a new configuration object
|
|
||||||
# @yield the given block will be evaluated in the context of the new object
|
|
||||||
def self.create(&block)
|
|
||||||
config = self.new
|
|
||||||
config.instance_eval(&block) if block_given?
|
|
||||||
config
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class SettingNotFoundError < RuntimeError; end
|
|
||||||
end
|
|
||||||
|
|
@ -1,65 +0,0 @@
|
||||||
module Configuration
|
|
||||||
# This object builds a chain of configuration providers to try to find
|
|
||||||
# a setting.
|
|
||||||
class LookupChain
|
|
||||||
def initialize
|
|
||||||
@provider = []
|
|
||||||
end
|
|
||||||
|
|
||||||
# Add a provider to the chain. Providers are tried in the order
|
|
||||||
# they are added, so the order is important.
|
|
||||||
#
|
|
||||||
# @param provider [#lookup]
|
|
||||||
# @param *args the arguments passed to the providers constructor
|
|
||||||
# @raise [ArgumentError] if an invalid provider is given
|
|
||||||
# @return [void]
|
|
||||||
def add_provider(provider, *args)
|
|
||||||
unless provider.instance_method_names.include?("lookup")
|
|
||||||
raise ArgumentError, "the given provider does not respond to lookup"
|
|
||||||
end
|
|
||||||
|
|
||||||
@provider << provider.new(*args)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# Tries all providers in the order they were added to provide a response
|
|
||||||
# for setting.
|
|
||||||
#
|
|
||||||
# @param setting [#to_s] settings should be underscore_case,
|
|
||||||
# nested settings should be separated by a dot
|
|
||||||
# @param *args further args passed to the provider
|
|
||||||
# @return [Array,String,Boolean,nil] whatever the provider provides
|
|
||||||
# is casted to a {String}, except for some special values
|
|
||||||
def lookup(setting, *args)
|
|
||||||
setting = setting.to_s
|
|
||||||
|
|
||||||
@provider.each do |provider|
|
|
||||||
begin
|
|
||||||
return special_value_or_string(provider.lookup(setting, *args))
|
|
||||||
rescue SettingNotFoundError; end
|
|
||||||
end
|
|
||||||
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
alias_method :[], :lookup
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def special_value_or_string(value)
|
|
||||||
if [TrueClass, FalseClass, NilClass, Array, Hash].include?(value.class)
|
|
||||||
return value
|
|
||||||
elsif value.is_a?(String)
|
|
||||||
return case value.strip
|
|
||||||
when "true" then true
|
|
||||||
when "false" then false
|
|
||||||
when "", "nil" then nil
|
|
||||||
else value
|
|
||||||
end
|
|
||||||
elsif value.respond_to?(:to_s)
|
|
||||||
return value.to_s
|
|
||||||
else
|
|
||||||
return value
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
module Configuration::Provider
|
|
||||||
# This provides a basic {#lookup} method for other providers to build
|
|
||||||
# upon. Childs are expected to define +lookup_path(path, *args)+ where
|
|
||||||
# +path+ will be passed an array of settings generated by splitting the
|
|
||||||
# called setting at the dots. The method should return nil if the setting
|
|
||||||
# wasn't found and {#lookup} will raise an {SettingNotFoundError} in that
|
|
||||||
# case.
|
|
||||||
class Base
|
|
||||||
def lookup(setting, *args)
|
|
||||||
result = lookup_path(setting.split("."), *args)
|
|
||||||
return result unless result.nil?
|
|
||||||
raise Configuration::SettingNotFoundError, "The setting #{setting} was not found"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
require Rails.root.join("lib", "configuration", "provider", "yaml")
|
|
||||||
require Rails.root.join("lib", "configuration", "provider", "env")
|
|
||||||
require Rails.root.join("lib", "configuration", "provider", "dynamic")
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
module Configuration::Provider
|
|
||||||
# This provider knows nothing upon initialization, however if you access
|
|
||||||
# a setting ending with +=+ and give one argument to that call it remembers
|
|
||||||
# that setting, stripping the +=+ and will return it on the next call
|
|
||||||
# without +=+.
|
|
||||||
class Dynamic < Base
|
|
||||||
def initialize
|
|
||||||
@settings = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
def lookup_path(settings_path, *args)
|
|
||||||
key = settings_path.join(".")
|
|
||||||
|
|
||||||
if key.end_with?("=") && args.length > 0
|
|
||||||
key = key.chomp("=")
|
|
||||||
value = args.first
|
|
||||||
value = value.get if value.respond_to?(:_proxy?) && value._proxy?
|
|
||||||
@settings[key] = value
|
|
||||||
end
|
|
||||||
|
|
||||||
@settings[key]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
module Configuration::Provider
|
|
||||||
# This provider looks for settings in the environment.
|
|
||||||
# For the setting +foo.bar_baz+ this provider will look for an
|
|
||||||
# environment variable +FOO_BAR_BAZ+, replacing all dots in the setting
|
|
||||||
# and upcasing the result. If an value contains +,+ it's split at them
|
|
||||||
# and returned as array.
|
|
||||||
class Env < Base
|
|
||||||
def lookup_path(settings_path, *args)
|
|
||||||
value = ENV[settings_path.join("_").upcase]
|
|
||||||
value = value.split(",") if value && value.include?(",")
|
|
||||||
value
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -1,52 +0,0 @@
|
||||||
require 'yaml'
|
|
||||||
|
|
||||||
module Configuration::Provider
|
|
||||||
# This provider tries to open a YAML file and does in nested lookups
|
|
||||||
# in it.
|
|
||||||
class YAML < Base
|
|
||||||
# @param file [String] the path to the file
|
|
||||||
# @param opts [Hash]
|
|
||||||
# @option opts [String] :namespace optionally set this as the root
|
|
||||||
# @option opts [Boolean] :required wheter or not to raise an error if
|
|
||||||
# the file or the namespace, if given, is not found. Defaults to +true+.
|
|
||||||
# @raise [ArgumentError] if the namespace isn't found in the file
|
|
||||||
# @raise [Errno:ENOENT] if the file isn't found
|
|
||||||
def initialize(file, opts = {})
|
|
||||||
@settings = {}
|
|
||||||
required = opts.has_key?(:required) ? opts.delete(:required) : true
|
|
||||||
|
|
||||||
@settings = ::YAML.load_file(file)
|
|
||||||
|
|
||||||
namespace = opts.delete(:namespace)
|
|
||||||
unless namespace.nil?
|
|
||||||
actual_settings = lookup_in_hash(namespace.split("."), @settings)
|
|
||||||
unless actual_settings.nil?
|
|
||||||
@settings = actual_settings
|
|
||||||
else
|
|
||||||
raise ArgumentError, "Namespace #{namespace} not found in #{file}" if required
|
|
||||||
end
|
|
||||||
end
|
|
||||||
rescue Errno::ENOENT => e
|
|
||||||
$stderr.puts "WARNING: configuration file #{file} not found, ensure it's present"
|
|
||||||
raise e if required
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
def lookup_path(settings_path, *args)
|
|
||||||
lookup_in_hash(settings_path, @settings)
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def lookup_in_hash(setting_path, hash)
|
|
||||||
setting = setting_path.shift
|
|
||||||
if hash.has_key?(setting)
|
|
||||||
if setting_path.length > 0 && hash[setting].is_a?(Hash)
|
|
||||||
return lookup_in_hash(setting_path, hash[setting]) if setting.length > 1
|
|
||||||
else
|
|
||||||
return hash[setting]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
module Configuration
|
|
||||||
# Proxy object to support nested settings
|
|
||||||
# Cavehat: Since this is always true, adding a ? at the end
|
|
||||||
# returns the value, if found, instead of the proxy object.
|
|
||||||
# So instead of +if settings.foo.bar+ use +if settings.foo.bar?+
|
|
||||||
# to check for boolean values, +if settings.foo.bar.nil?+ to
|
|
||||||
# check for nil values, +if settings.foo.bar.present?+ to check for
|
|
||||||
# empty values if you're in Rails and call {#get} to actually return the value,
|
|
||||||
# commonly when doing +settings.foo.bar.get || 'default'+. If a setting
|
|
||||||
# ends with +=+ is too called directly, just like with +?+.
|
|
||||||
class Proxy < BasicObject
|
|
||||||
COMMON_KEY_NAMES = [:key, :method]
|
|
||||||
|
|
||||||
# @param lookup_chain [#lookup]
|
|
||||||
def initialize(lookup_chain)
|
|
||||||
@lookup_chain = lookup_chain
|
|
||||||
@setting = ""
|
|
||||||
end
|
|
||||||
|
|
||||||
def !
|
|
||||||
!self.get
|
|
||||||
end
|
|
||||||
|
|
||||||
def !=(other)
|
|
||||||
self.get != other
|
|
||||||
end
|
|
||||||
|
|
||||||
def ==(other)
|
|
||||||
self.get == other
|
|
||||||
end
|
|
||||||
|
|
||||||
def _proxy?
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
def respond_to?(method, include_private=false)
|
|
||||||
method == :_proxy? || self.get.respond_to?(method, include_private)
|
|
||||||
end
|
|
||||||
|
|
||||||
def send(*args, &block)
|
|
||||||
self.__send__(*args, &block)
|
|
||||||
end
|
|
||||||
|
|
||||||
def method_missing(setting, *args, &block)
|
|
||||||
unless COMMON_KEY_NAMES.include? setting
|
|
||||||
target = self.get
|
|
||||||
if !(target.respond_to?(:_proxy?) && target._proxy?) && target.respond_to?(setting)
|
|
||||||
return target.send(setting, *args, &block)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
setting = setting.to_s
|
|
||||||
|
|
||||||
self.append_setting(setting)
|
|
||||||
|
|
||||||
return self.get(*args) if setting.end_with?("?") || setting.end_with?("=")
|
|
||||||
|
|
||||||
self
|
|
||||||
end
|
|
||||||
|
|
||||||
# Get the setting at the current path, if found.
|
|
||||||
# (see LookupChain#lookup)
|
|
||||||
def get(*args)
|
|
||||||
setting = @setting[1..-1]
|
|
||||||
return unless setting
|
|
||||||
val = @lookup_chain.lookup(setting.chomp("?"), *args)
|
|
||||||
val
|
|
||||||
end
|
|
||||||
|
|
||||||
protected
|
|
||||||
def append_setting(setting)
|
|
||||||
@setting << "."
|
|
||||||
@setting << setting
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -1,67 +0,0 @@
|
||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
class InvalidConfigurationProvider; end
|
|
||||||
class ValidConfigurationProvider
|
|
||||||
def lookup(setting, *args); end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe Configuration::LookupChain do
|
|
||||||
subject { described_class.new }
|
|
||||||
|
|
||||||
describe "#add_provider" do
|
|
||||||
it "adds a valid provider" do
|
|
||||||
expect {
|
|
||||||
subject.add_provider ValidConfigurationProvider
|
|
||||||
}.to change { subject.instance_variable_get(:@provider).size }.by 1
|
|
||||||
end
|
|
||||||
|
|
||||||
it "doesn't add an invalid provider" do
|
|
||||||
expect {
|
|
||||||
subject.add_provider InvalidConfigurationProvider
|
|
||||||
}.to raise_error ArgumentError
|
|
||||||
end
|
|
||||||
|
|
||||||
it "passes extra args to the provider" do
|
|
||||||
ValidConfigurationProvider.should_receive(:new).with(:extra)
|
|
||||||
subject.add_provider ValidConfigurationProvider, :extra
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "#lookup" do
|
|
||||||
before(:all) do
|
|
||||||
subject.add_provider ValidConfigurationProvider
|
|
||||||
subject.add_provider ValidConfigurationProvider
|
|
||||||
@provider = subject.instance_variable_get(:@provider)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "it tries all providers" do
|
|
||||||
setting = "some.setting"
|
|
||||||
@provider.each do |provider|
|
|
||||||
provider.should_receive(:lookup).with(setting).and_raise(Configuration::SettingNotFoundError)
|
|
||||||
end
|
|
||||||
|
|
||||||
subject.lookup(setting)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "stops if a value is found" do
|
|
||||||
@provider[0].should_receive(:lookup).and_return("something")
|
|
||||||
@provider[1].should_not_receive(:lookup)
|
|
||||||
subject.lookup("bla")
|
|
||||||
end
|
|
||||||
|
|
||||||
it "converts numbers to strings" do
|
|
||||||
@provider[0].stub(:lookup).and_return(5)
|
|
||||||
subject.lookup("foo").should == "5"
|
|
||||||
end
|
|
||||||
|
|
||||||
it "does not convert false to a string" do
|
|
||||||
@provider[0].stub(:lookup).and_return(false)
|
|
||||||
subject.lookup("enable").should be_false
|
|
||||||
end
|
|
||||||
|
|
||||||
it "returns nil if no value is found" do
|
|
||||||
@provider.each { |p| p.stub(:lookup).and_raise(Configuration::SettingNotFoundError) }
|
|
||||||
subject.lookup("not.me").should be_nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe Configuration::Provider::Dynamic do
|
|
||||||
subject { described_class.new }
|
|
||||||
describe "#lookup_path" do
|
|
||||||
it "returns nil if the setting was never set" do
|
|
||||||
subject.lookup_path(["not_me"]).should be_nil
|
|
||||||
end
|
|
||||||
|
|
||||||
it "remembers the setting if it ends with =" do
|
|
||||||
subject.lookup_path(["find_me", "later="], "there")
|
|
||||||
subject.lookup_path(["find_me", "later"]).should == "there"
|
|
||||||
end
|
|
||||||
|
|
||||||
it "calls .get on the argument if a proxy object is given" do
|
|
||||||
proxy = mock
|
|
||||||
proxy.stub(:respond_to?).and_return(true)
|
|
||||||
proxy.stub(:_proxy?).and_return(true)
|
|
||||||
proxy.should_receive(:get)
|
|
||||||
subject.lookup_path(["bla="], proxy)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe Configuration::Provider::Env do
|
|
||||||
subject { described_class.new }
|
|
||||||
let(:existing_path) { ['existing', 'setting']}
|
|
||||||
let(:not_existing_path) { ['not', 'existing', 'path']}
|
|
||||||
let(:array_path) { ['array'] }
|
|
||||||
before(:all) do
|
|
||||||
ENV['EXISTING_SETTING'] = "there"
|
|
||||||
ENV['ARRAY'] = "foo,bar,baz"
|
|
||||||
end
|
|
||||||
|
|
||||||
after(:all) do
|
|
||||||
ENV['EXISTING_SETTING'] = nil
|
|
||||||
ENV['ARRAY'] = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#lookup_path' do
|
|
||||||
it "joins and upcases the path" do
|
|
||||||
ENV.should_receive(:[]).with("EXISTING_SETTING")
|
|
||||||
subject.lookup_path(existing_path)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "returns nil if the setting isn't available" do
|
|
||||||
subject.lookup_path(not_existing_path).should be_nil
|
|
||||||
end
|
|
||||||
|
|
||||||
it "makes an array out of comma separated values" do
|
|
||||||
subject.lookup_path(array_path).should == ["foo", "bar", "baz"]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe Configuration::Provider::YAML do
|
|
||||||
let(:settings) { {"toplevel" => "bar",
|
|
||||||
"some" => {
|
|
||||||
"nested" => { "some" => "lala", "setting" => "foo"}
|
|
||||||
}
|
|
||||||
} }
|
|
||||||
|
|
||||||
describe "#initialize" do
|
|
||||||
it "loads the file" do
|
|
||||||
file = "foobar.yml"
|
|
||||||
::YAML.should_receive(:load_file).with(file).and_return({})
|
|
||||||
described_class.new file
|
|
||||||
end
|
|
||||||
|
|
||||||
it "raises if the file is not found" do
|
|
||||||
::YAML.stub(:load_file).and_raise(Errno::ENOENT)
|
|
||||||
expect {
|
|
||||||
described_class.new "foo"
|
|
||||||
}.to raise_error Errno::ENOENT
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
context "with a namespace" do
|
|
||||||
it "looks in the file for that namespace" do
|
|
||||||
namespace = "some"
|
|
||||||
::YAML.stub(:load_file).and_return(settings)
|
|
||||||
provider = described_class.new 'bla', namespace: namespace
|
|
||||||
provider.instance_variable_get(:@settings).should == settings[namespace]
|
|
||||||
end
|
|
||||||
|
|
||||||
it "raises if the namespace isn't found" do
|
|
||||||
::YAML.stub(:load_file).and_return({})
|
|
||||||
expect {
|
|
||||||
described_class.new 'bla', namespace: "foo"
|
|
||||||
}.to raise_error ArgumentError
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context "with required set to false" do
|
|
||||||
it "doesn't raise if a file isn't found" do
|
|
||||||
::YAML.stub(:load_file).and_raise(Errno::ENOENT)
|
|
||||||
expect {
|
|
||||||
described_class.new "not_me", required: false
|
|
||||||
}.not_to raise_error Errno::ENOENT
|
|
||||||
end
|
|
||||||
|
|
||||||
it "doesn't raise if a namespace isn't found" do
|
|
||||||
::YAML.stub(:load_file).and_return({})
|
|
||||||
expect {
|
|
||||||
described_class.new 'bla', namespace: "foo", required: false
|
|
||||||
}.not_to raise_error ArgumentError
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "#lookup_path" do
|
|
||||||
before do
|
|
||||||
::YAML.stub(:load_file).and_return(settings)
|
|
||||||
@provider = described_class.new 'dummy'
|
|
||||||
end
|
|
||||||
|
|
||||||
it "looks up the whole nesting" do
|
|
||||||
@provider.lookup_path(["some", "nested", "some"]).should == settings["some"]["nested"]["some"]
|
|
||||||
end
|
|
||||||
|
|
||||||
it "returns nil if no setting is found" do
|
|
||||||
@provider.lookup_path(["not_me"]).should be_nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe Configuration::Provider::Base do
|
|
||||||
subject { described_class.new }
|
|
||||||
describe "#lookup" do
|
|
||||||
it "calls #lookup_path with the setting as array" do
|
|
||||||
subject.should_receive(:lookup_path).with(["foo", "bar"]).and_return("something")
|
|
||||||
subject.lookup("foo.bar").should == "something"
|
|
||||||
end
|
|
||||||
|
|
||||||
it "raises SettingNotFoundError if the #lookup_path returns nil" do
|
|
||||||
subject.should_receive(:lookup_path).and_return(nil)
|
|
||||||
expect {
|
|
||||||
subject.lookup("bla")
|
|
||||||
}.to raise_error Configuration::SettingNotFoundError
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe Configuration::Proxy do
|
|
||||||
let(:lookup_chain) { mock }
|
|
||||||
before do
|
|
||||||
lookup_chain.stub(:lookup).and_return("something")
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "#method_missing" do
|
|
||||||
it "calls #get if the method ends with a ?" do
|
|
||||||
lookup_chain.should_receive(:lookup).with("enable").and_return(false)
|
|
||||||
described_class.new(lookup_chain).method_missing(:enable?)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "calls #get if the method ends with a =" do
|
|
||||||
lookup_chain.should_receive(:lookup).with("url=").and_return(false)
|
|
||||||
described_class.new(lookup_chain).method_missing(:url=)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "#get" do
|
|
||||||
[:to_str, :to_s, :to_xml, :respond_to?, :present?, :!=,
|
|
||||||
:each, :try, :size, :length, :count, :==, :=~, :gsub, :blank?, :chop,
|
|
||||||
:start_with?, :end_with?].each do |method|
|
|
||||||
it "is called for accessing #{method} on the proxy" do
|
|
||||||
target = mock
|
|
||||||
lookup_chain.should_receive(:lookup).and_return(target)
|
|
||||||
target.should_receive(method).and_return("something")
|
|
||||||
described_class.new(lookup_chain).something.__send__(method, mock)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
described_class::COMMON_KEY_NAMES.each do |method|
|
|
||||||
it "is not called for accessing #{method} on the proxy" do
|
|
||||||
target = mock
|
|
||||||
lookup_chain.should_not_receive(:lookup).and_return(target)
|
|
||||||
target.should_not_receive(method).and_return("something")
|
|
||||||
described_class.new(lookup_chain).something.__send__(method, mock)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
it "strips leading dots" do
|
|
||||||
lookup_chain.should_receive(:lookup).with("foo.bar").and_return("something")
|
|
||||||
described_class.new(lookup_chain).foo.bar.get
|
|
||||||
end
|
|
||||||
|
|
||||||
it "returns nil if no setting is given" do
|
|
||||||
described_class.new(lookup_chain).get.should be_nil
|
|
||||||
end
|
|
||||||
|
|
||||||
it "strips ? at the end" do
|
|
||||||
lookup_chain.should_receive(:lookup).with("foo.bar").and_return("something")
|
|
||||||
described_class.new(lookup_chain).foo.bar?
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -2,9 +2,9 @@ require 'spec_helper'
|
||||||
|
|
||||||
describe Configuration::Methods do
|
describe Configuration::Methods do
|
||||||
before(:all) do
|
before(:all) do
|
||||||
@settings = Configuration::Settings.create do
|
@settings = Configurate::Settings.create do
|
||||||
add_provider Configuration::Provider::Dynamic
|
add_provider Configurate::Provider::Dynamic
|
||||||
add_provider Configuration::Provider::Env
|
add_provider Configurate::Provider::Env
|
||||||
extend Configuration::Methods
|
extend Configuration::Methods
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe Configuration::Settings do
|
|
||||||
describe "#method_missing" do
|
|
||||||
subject { described_class.create }
|
|
||||||
|
|
||||||
it "delegates the call to a new proxy object" do
|
|
||||||
proxy = mock
|
|
||||||
Configuration::Proxy.should_receive(:new).and_return(proxy)
|
|
||||||
proxy.should_receive(:method_missing).with(:some_setting).and_return("foo")
|
|
||||||
subject.some_setting
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
[:lookup, :add_provider, :[]].each do |method|
|
|
||||||
describe "#{method}" do
|
|
||||||
subject { described_class.create }
|
|
||||||
|
|
||||||
it "delegates the call to #lookup_chain" do
|
|
||||||
subject.lookup_chain.should_receive(method)
|
|
||||||
subject.send(method)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
Loading…
Reference in a new issue