econfig 2.0.0 → 2.1.0

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