econfig 2.0.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f4ba24341ee1636314ae2fa645edd20fddacedf8
4
- data.tar.gz: 8741ff1333019ae2ef21773bedf700beb497a3e0
3
+ metadata.gz: b0662ed0e8cd53281753072640fe6b72f715410b
4
+ data.tar.gz: e32b3e83e8197a4c353e184f01ad91bdbf89248d
5
5
  SHA512:
6
- metadata.gz: 8cdb9f56898c683166eb2fa29dc107fcba153e2daa0ea8358419504be251e39013339f9fd438835a368db05385bddc531fe391baac13923f3abff052f0c48f55
7
- data.tar.gz: 6c1e783e2e0c2ba72ec2df956370da81269ee185faf6f1cec7bf2c92cb245bef4939eab20accaf7456e847a58b971c4c450170f770e980004579ef61b9b2f92e
6
+ metadata.gz: 3411a8decc879040d95eaff1124220939c735857777d35689d117cb6198893dae30a44e4d4144066bc427dd33bf021f827554599f507a647ac240265cd4ed742
7
+ data.tar.gz: ccb73c2eb936443fd533620a2bead57c656325897cd97becec2feaadcff048f757ec3403e0d34d1b96f8d093ee53f3e90b8decf189dfe2a7bc730a1d5b22bc4f
data/README.md CHANGED
@@ -19,20 +19,36 @@ gem "econfig", require: "econfig/rails"
19
19
 
20
20
  ## Accessing config options
21
21
 
22
- Extend your main application module with the Econfig shortcut. In Rails, you'll
23
- want to add this in `config/application.rb`:
22
+ Extend your main application module with the Econfig shortcut.
23
+
24
+ In Rails, you'll want to add this in `config/application.rb`:
24
25
 
25
26
  ``` ruby
26
27
  module MyApp
27
28
  extend Econfig::Shortcut
28
29
 
29
30
  class Application < Rails::Application
30
-
31
+ #
31
32
  end
32
33
  end
33
34
  ```
34
35
 
35
- Now you can access configuration like this:
36
+ In a modular Sinatra application, extend your controller class and copy its settings to Econfig in `app.rb`:
37
+ ``` ruby
38
+ require 'sinatra'
39
+ require 'econfig'
40
+
41
+ class MyApp < Sinatra::Base
42
+ extend Econfig::Shortcut
43
+
44
+ Econfig.env = settings.environment.to_s
45
+ Econfig.root = settings.root
46
+
47
+ # …
48
+ end
49
+ ```
50
+
51
+ In either case, you can now you can access configuration like this:
36
52
 
37
53
  ``` ruby
38
54
  MyApp.config.aws_access_key_id
@@ -16,7 +16,7 @@ module Econfig
16
16
 
17
17
  attr_accessor :root, :env, :instance
18
18
 
19
- def_delegators :instance, :backends, :default_write_backend, :default_write_backend=
19
+ def_delegators :instance, :backends, :cast, :default_write_backend, :default_write_backend=
20
20
  end
21
21
  end
22
22
 
@@ -1,5 +1,16 @@
1
+ require "active_record"
2
+
1
3
  module Econfig
2
4
  class ActiveRecord
5
+ MISSING_TABLE_WARNING = <<-WARNING.gsub(/^ */, "")
6
+ =======================================================================
7
+ Econfig table not found. Please add the configuration table by running:
8
+
9
+ rails generate econfig:migration
10
+ rake db:migrate
11
+ =======================================================================
12
+ WARNING
13
+
3
14
  class Option < ::ActiveRecord::Base
4
15
  attr_accessible :key, :value rescue nil
5
16
  self.table_name = "econfig_options"
@@ -7,13 +18,28 @@ module Econfig
7
18
  validates_presence_of :key
8
19
  end
9
20
 
21
+ def keys
22
+ Set.new(Option.pluck(:key))
23
+ rescue ::ActiveRecord::StatementInvalid
24
+ warn MISSING_TABLE_WARNING
25
+ Set.new([])
26
+ end
27
+
10
28
  def get(key)
11
- Option.find_by_key(key).try(:value)
29
+ if option = Option.find_by_key(key)
30
+ option.value
31
+ else
32
+ yield if block_given?
33
+ end
34
+ rescue ::ActiveRecord::StatementInvalid
35
+ warn MISSING_TABLE_WARNING
12
36
  end
13
37
 
14
38
  def set(key, value)
15
39
  option = Option.where(:key => key).first_or_initialize
16
40
  option.update_attributes!(:value => value)
41
+ rescue ::ActiveRecord::StatementInvalid
42
+ warn MISSING_TABLE_WARNING
17
43
  end
18
44
  end
19
45
  end
@@ -1,3 +1,4 @@
1
+ # encoding: utf-8
1
2
  module Econfig
2
3
  class BackendCollection
3
4
  include Enumerable
@@ -6,6 +7,16 @@ module Econfig
6
7
  @backends = []
7
8
  end
8
9
 
10
+ def keys
11
+ @backends.reduce(Set.new) do |agg, (name, backend)|
12
+ if backend.respond_to?(:keys)
13
+ agg.union(backend.keys)
14
+ else
15
+ agg
16
+ end
17
+ end
18
+ end
19
+
9
20
  def [](name)
10
21
  pair = @backends.assoc(name)
11
22
  pair.last if pair
@@ -20,23 +31,23 @@ module Econfig
20
31
  end
21
32
 
22
33
  def push(name, backend)
23
- exists(name)
34
+ exists?(name)
24
35
  @backends.push([name, backend])
25
36
  end
26
37
  alias_method :use, :push
27
38
 
28
39
  def unshift(name, backend)
29
- exists(name)
40
+ exists?(name)
30
41
  @backends.unshift([name, backend])
31
42
  end
32
43
 
33
44
  def insert_before(other, name, backend)
34
- exists(name)
45
+ exists?(name)
35
46
  @backends.insert(index_of!(other), [name, backend])
36
47
  end
37
48
 
38
49
  def insert_after(other, name, backend)
39
- exists(name)
50
+ exists?(name)
40
51
  @backends.insert(index_of!(other) + 1, [name, backend])
41
52
  end
42
53
 
@@ -44,14 +55,27 @@ module Econfig
44
55
  @backends.delete_at(index_of!(name))
45
56
  end
46
57
 
47
- def backend_for(key)
48
- result = @backends.find { |(n, b)| b.has_key?(key) }
49
- result[1] if result
58
+ def get(key)
59
+ @backends.each do |(name, backend)|
60
+ has_key = true
61
+
62
+ if backend.respond_to?(:has_key?)
63
+ has_key = backend.has_key?(key)
64
+ value = backend.get(key) if has_key
65
+ else
66
+ value = backend.get(key) { has_key = false }
67
+ end
68
+
69
+ has_key or next
70
+ return value
71
+ end
72
+
73
+ yield if block_given?
50
74
  end
51
75
 
52
76
  private
53
77
 
54
- def exists(name)
78
+ def exists?(name)
55
79
  raise KeyError, "#{name} is already set" if index_of(name)
56
80
  end
57
81
 
@@ -2,27 +2,39 @@ module Econfig
2
2
  class Configuration
3
3
  attr_accessor :default_write_backend
4
4
 
5
- def backends
5
+ attr_reader :backends, :casts
6
+
7
+ def initialize
6
8
  @backends ||= BackendCollection.new
9
+ @casts ||= {}
10
+ end
11
+
12
+ def cast(key, &block)
13
+ casts[key.to_s] = block
14
+ end
15
+
16
+ def keys
17
+ backends.keys
7
18
  end
8
19
 
9
20
  def fetch(key)
10
- key = key.to_s
11
- backend = backends.backend_for(key)
12
- if backend
13
- backend.get(key)
14
- else
21
+ get(key) do
15
22
  raise Econfig::NotFound, "configuration key '#{key}' is not set"
16
23
  end
17
24
  end
18
25
 
19
- def [](key)
26
+ def get(key)
20
27
  key = key.to_s
21
- backend = backends.backend_for(key)
22
- backend.get(key) if backend
28
+ value = backends.get(key) do
29
+ yield if block_given?
30
+ return nil
31
+ end
32
+ value = casts[key].call(value) if casts[key]
33
+ value
23
34
  end
35
+ alias_method :[], :get
24
36
 
25
- def []=(backend_name = default_write_backend, key, value)
37
+ def set(backend_name = default_write_backend, key, value)
26
38
  raise ArgumentError, "no backend given" unless backend_name
27
39
  if backend = backends[backend_name]
28
40
  backend.set(key.to_s, value)
@@ -30,6 +42,7 @@ module Econfig
30
42
  raise KeyError, "#{backend_name} is not set"
31
43
  end
32
44
  end
45
+ alias_method :[]=, :set
33
46
 
34
47
  def method_missing(name, *args)
35
48
  if respond_to?(name)
@@ -5,6 +5,10 @@ module Econfig
5
5
  @options = {}
6
6
  end
7
7
 
8
+ def keys
9
+ Set.new(@options.keys)
10
+ end
11
+
8
12
  def has_key?(key)
9
13
  @options.has_key?(key)
10
14
  end
@@ -18,5 +22,11 @@ module Econfig
18
22
  @options[key] = value
19
23
  end
20
24
  end
25
+
26
+ def clear
27
+ @mutex.synchronize do
28
+ @options.clear
29
+ end
30
+ end
21
31
  end
22
32
  end
@@ -4,6 +4,10 @@ module Econfig
4
4
  @redis = redis
5
5
  end
6
6
 
7
+ def keys
8
+ Set.new(@redis.keys)
9
+ end
10
+
7
11
  def has_key?(key)
8
12
  @redis.exists(key)
9
13
  end
@@ -1,3 +1,3 @@
1
1
  module Econfig
2
- VERSION = "2.0.0"
2
+ VERSION = "2.1.0"
3
3
  end
@@ -9,6 +9,10 @@ module Econfig
9
9
  @options = nil
10
10
  end
11
11
 
12
+ def keys
13
+ Set.new(options.keys)
14
+ end
15
+
12
16
  def get(key)
13
17
  options[key]
14
18
  end
@@ -17,6 +17,15 @@ describe Econfig::ActiveRecord do
17
17
  raise ActiveRecord::Rollback
18
18
  end
19
19
  end
20
+
21
+ describe "#keys" do
22
+ it "returns a list of set keys" do
23
+ backend.set("foo", "123")
24
+ backend.set("bar", "664")
25
+ backend.keys.should eq(Set.new(["foo", "bar"]))
26
+ end
27
+ end
28
+
20
29
  describe "#get" do
21
30
  it "fetches a previously set option" do
22
31
  backend.set("foo", "bar")
@@ -31,6 +40,15 @@ describe Econfig::ActiveRecord do
31
40
  it "returns nil if option is not set" do
32
41
  backend.get("foo").should be_nil
33
42
  end
43
+
44
+ it "yields if option is not set" do
45
+ backend.get("foo") { "blah" }.should eq("blah")
46
+ end
47
+
48
+ it "ignores block if set" do
49
+ backend.set("foo", "bar")
50
+ backend.get("foo") { raise "blah" }.should eq("bar")
51
+ end
34
52
  end
35
53
 
36
54
  describe "#set" do
@@ -1,6 +1,6 @@
1
1
  describe Econfig::Configuration do
2
- let(:backend) { double }
3
- let(:other_backend) { double }
2
+ let(:backend) { double("backend") }
3
+ let(:other_backend) { double("other backend") }
4
4
  let(:config) { Econfig::Configuration.new }
5
5
 
6
6
  before do
@@ -8,6 +8,19 @@ describe Econfig::Configuration do
8
8
  config.backends.push(:other, other_backend)
9
9
  end
10
10
 
11
+ describe "#keys" do
12
+ it "returns the union of all keys" do
13
+ backend.stub(:keys).and_return(Set.new(["foo", "bar", "baz"]))
14
+ other_backend.stub(:keys).and_return(Set.new(["bar", "monkey"]))
15
+ config.keys.should == Set.new(["foo", "bar", "baz", "monkey"])
16
+ end
17
+
18
+ it "skips over backends which don't return keys" do
19
+ other_backend.stub(:keys).and_return(Set.new(["bar", "monkey"]))
20
+ config.keys.should == Set.new(["bar", "monkey"])
21
+ end
22
+ end
23
+
11
24
  describe "#[]" do
12
25
  it "returns response from first backend" do
13
26
  backend.stub(:has_key?).with("foobar").and_return(true)
@@ -21,6 +34,19 @@ describe Econfig::Configuration do
21
34
  config[:foobar].should == "elephant"
22
35
  end
23
36
 
37
+ it "casts value if it exists" do
38
+ config.cast(:foobar) { |val| val.to_i + 10 }
39
+ backend.stub(:get).with("foobar").and_return("123")
40
+ config[:foobar].should == 133
41
+ end
42
+
43
+ it "does not cast if there is no value" do
44
+ config.cast(:foobar) { |val| raise "should not be here" }
45
+ backend.stub(:has_key?).with("foobar").and_return(false)
46
+ other_backend.stub(:has_key?).with("foobar").and_return(false)
47
+ config[:foobar].should == nil
48
+ end
49
+
24
50
  it "tries multiple backends until it finds a response" do
25
51
  backend.stub(:has_key?).with("foobar").and_return(false)
26
52
  other_backend.stub(:has_key?).with("foobar").and_return(true)
@@ -28,6 +54,12 @@ describe Econfig::Configuration do
28
54
  config["foobar"].should == "elephant"
29
55
  end
30
56
 
57
+ it "tries multiple backends which yield from get until it finds one which doesn't" do
58
+ backend.stub(:get).with("foobar").and_yield
59
+ other_backend.stub(:get).with("foobar").and_return("elephant")
60
+ config["foobar"].should == "elephant"
61
+ end
62
+
31
63
  it "returns nil if the key can't be found in any backend" do
32
64
  backend.stub(:has_key?).with("foobar").and_return(false)
33
65
  other_backend.stub(:has_key?).with("foobar").and_return(false)
@@ -69,6 +101,19 @@ describe Econfig::Configuration do
69
101
  config.fetch("foobar").should == "elephant"
70
102
  end
71
103
 
104
+ it "casts value if it exists" do
105
+ config.cast(:foobar) { |val| val.to_i + 10 }
106
+ backend.stub(:get).with("foobar").and_return("123")
107
+ config.fetch(:foobar).should == 133
108
+ end
109
+
110
+ it "does not cast if there is no value" do
111
+ config.cast(:foobar) { |val| raise "should not be here" }
112
+ backend.stub(:has_key?).with("foobar").and_return(false)
113
+ other_backend.stub(:has_key?).with("foobar").and_return(false)
114
+ expect { config.fetch("foobar") }.to raise_error(Econfig::NotFound)
115
+ end
116
+
72
117
  it "tries multiple backends until it finds a response" do
73
118
  backend.stub(:has_key?).with("foobar").and_return(false)
74
119
  other_backend.stub(:has_key?).with("foobar").and_return(true)
@@ -5,6 +5,12 @@ describe Econfig::ENV do
5
5
  ENV["FOO_BAR"] = "monkey"
6
6
  end
7
7
 
8
+ describe "#keys" do
9
+ it "is not supported because it would return a lot of junk" do
10
+ backend.respond_to?(:keys).should be_falsy
11
+ end
12
+ end
13
+
8
14
  describe "#has_key?" do
9
15
  it "returns true if key exists" do
10
16
  backend.has_key?("foo_bar").should eq(true)
@@ -1,6 +1,14 @@
1
1
  describe Econfig::Memory do
2
2
  let(:backend) { Econfig::Memory.new }
3
3
 
4
+ describe "#keys" do
5
+ it "returns a list of set keys" do
6
+ backend.set("foo", "123")
7
+ backend.set("bar", "664")
8
+ backend.keys.should eq(Set.new(["foo", "bar"]))
9
+ end
10
+ end
11
+
4
12
  describe "#has_key?" do
5
13
  it "returns true if key exists" do
6
14
  backend.set("foo", "bar")
@@ -18,4 +26,12 @@ describe Econfig::Memory do
18
26
  backend.get("foo").should == "bar"
19
27
  end
20
28
  end
29
+
30
+ describe "#clear" do
31
+ it "clears all set keys" do
32
+ backend.set("foo", "bar")
33
+ backend.clear
34
+ backend.has_key?("foo").should be_falsy
35
+ end
36
+ end
21
37
  end
@@ -8,6 +8,14 @@ describe Econfig::Redis do
8
8
  redis.flushdb
9
9
  end
10
10
 
11
+ describe "#keys" do
12
+ it "returns a list of set keys" do
13
+ backend.set("foo", "123")
14
+ backend.set("bar", "664")
15
+ backend.keys.should eq(Set.new(["foo", "bar"]))
16
+ end
17
+ end
18
+
11
19
  describe "#has_key?" do
12
20
  it "returns true if key exists" do
13
21
  backend.set("foo", "bar")
@@ -2,3 +2,13 @@ require "econfig"
2
2
 
3
3
  Econfig.root = File.dirname(__FILE__)
4
4
  Econfig.env = "test"
5
+
6
+ RSpec.configure do |config|
7
+ config.expect_with :rspec do |c|
8
+ c.syntax = [:expect, :should]
9
+ end
10
+
11
+ config.mock_with :rspec do |c|
12
+ c.syntax = [:expect, :should]
13
+ end
14
+ end
@@ -1,6 +1,12 @@
1
1
  describe Econfig::YAML do
2
2
  let(:backend) { Econfig::YAML.new("config/app.yml") }
3
3
 
4
+ describe "#keys" do
5
+ it "returns keys set in backend" do
6
+ expect(backend.keys).to eq(Set.new(["quox", "envir"]))
7
+ end
8
+ end
9
+
4
10
  describe "#has_key?" do
5
11
  it "returns true if option exists" do
6
12
  expect(backend.has_key?("quox")).to eq(true)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: econfig
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonas Nicklas
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-02-23 00:00:00.000000000 Z
12
+ date: 2018-10-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -141,7 +141,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
141
141
  version: '0'
142
142
  requirements: []
143
143
  rubyforge_project:
144
- rubygems_version: 2.4.3
144
+ rubygems_version: 2.6.13
145
145
  signing_key:
146
146
  specification_version: 4
147
147
  summary: Congifure Ruby apps