a9n 0.3.4 → 0.4.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: f995c7f50ba67e72854fae222d3f3d1d56954e5d
4
- data.tar.gz: 85396eed16848d240fab8ede3ac86054bcb9078d
3
+ metadata.gz: 5f1aa00ff577227a9d07088e0053ea48814a8816
4
+ data.tar.gz: 932f917737c5c1c6cdb6919a9b16a1127a0a1c8f
5
5
  SHA512:
6
- metadata.gz: fa210dc6b9944ee7c4e33fa06b0cc95f63d8393e2fb6c5eed6dcf687af48ce161454cfda0cce1029bf42b048e70a1544c42044912a5f96dea9a9b38015a77905
7
- data.tar.gz: a31bb71f27ba83c90106a1138582b40c6fb695df20a14307772bcf04c4fc0a7e22bc255f57b07b14a9f05138ae0a87125d617de803081740bf977cd597a0c00c
6
+ metadata.gz: 1e69852a57a9f29d640d4983dfec8406c7943b038d07a5b58a441461a2f2ae7df8cfc6489c3df784dcb1b698a1c66ad8aeb4519c21c9bf00218217cc6478a507
7
+ data.tar.gz: d578632bc24b83cbfcdc835f7a76f727ba850bd527134bdd08940823af9a49d3a6d9d9655401d3428e5fa115724bdbb8c45ec21caf11a47a3346ea014ff9acff
@@ -1,9 +1,8 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.9.3
4
3
  - 2.0.0
5
- - 2.1.2
6
- - jruby-19mode
4
+ - 2.1.5
5
+ - 2.2.0
7
6
  addons:
8
7
  code_climate:
9
8
  repo_token: 9aa2aa2432639c57772b6917ad9da468709e5536b75617575b02b35201a2eaf8
data/README.md CHANGED
@@ -10,7 +10,7 @@
10
10
  [codeclimate]: https://codeclimate.com/github/knapo/a9n
11
11
  [coverage]: https://codeclimate.com/github/knapo/a9n
12
12
 
13
- A9n is a simple tool to keep ruby/rails apps configuration maintanable and verifiable. It supports Rails 2.x, 3.x, 4.x and Ruby 1.9, 2.0. 2.1. Ruby 1.8 is not supported since version 0.1.2.
13
+ A9n is a simple tool to keep ruby/rails apps configuration maintanable and verifiable. It supports Rails 2.x, 3.x, 4.x and Ruby 2.0. 2.1, 2.2. Ruby 1.8 is not supported since version 0.1.2. Ruby 1.9 is not supported since version 0.4.0.
14
14
 
15
15
  Why it's named a9n? It's a numeronym for application (where 9 stands for the number of letters between the first **a** and last **n**, similar to i18n or l10n).
16
16
 
data/lib/a9n.rb CHANGED
@@ -6,6 +6,8 @@ require "yaml"
6
6
  require "erb"
7
7
 
8
8
  module A9n
9
+ extend SingleForwardable
10
+
9
11
  class ConfigurationNotLoaded < StandardError; end
10
12
  class MissingConfigurationData < StandardError; end
11
13
  class MissingConfigurationVariables < StandardError; end
@@ -47,19 +49,6 @@ module A9n
47
49
  ENV[name]
48
50
  end
49
51
 
50
- def fetch(*args)
51
- scope(DEFAULT_SCOPE).fetch(*args)
52
- end
53
-
54
- def scope(name)
55
- load unless instance_variable_defined?(var_name_for(name))
56
- instance_variable_get(var_name_for(name))
57
- end
58
-
59
- def var_name_for(file)
60
- :"@#{File.basename(file.to_s).split('.').first}"
61
- end
62
-
63
52
  def default_files
64
53
  files = Dir[root.join("config/#{DEFAULT_SCOPE}.#{EXTENSION_LIST}").to_s]
65
54
  files += Dir[root.join("config/a9n/*.#{EXTENSION_LIST}")]
@@ -67,28 +56,48 @@ module A9n
67
56
  end
68
57
 
69
58
  def load(*files)
70
- if files.empty?
71
- files = default_files
72
- else
73
- files = get_absolute_paths_for(files)
74
- end
75
- files.map do |file|
76
- instance_variable_set(var_name_for(file), A9n::Loader.new(file, env).get)
77
- end
59
+ files = files.empty? ? default_files : get_absolute_paths_for(files)
60
+ files.map { |file| load_file(file) }
61
+ end
62
+
63
+ def storage
64
+ @storage ||= A9n::Struct.new
78
65
  end
79
66
 
80
67
  def method_missing(name, *args)
81
- if scope(name).is_a?(A9n::Struct)
82
- scope(name)
68
+ load if storage.empty?
69
+ storage.send(name)
70
+ end
71
+
72
+ private
73
+
74
+ def load_file(file)
75
+ scope_name = scope_name_from_file(file)
76
+ scope_data = A9n::Loader.new(file, env).get
77
+ setup_scope(scope_name, scope_data)
78
+ end
79
+
80
+ def setup_scope(name, data)
81
+ if default_scope?(name)
82
+ storage.merge(data)
83
+ def_delegators :storage, *data.keys
83
84
  else
84
- scope(DEFAULT_SCOPE).send(name, *args)
85
+ storage[name] = data
86
+ def_delegators :storage, name
85
87
  end
88
+ return data
86
89
  end
87
90
 
88
- private
91
+ def scope_name_from_file(file)
92
+ File.basename(file.to_s).split('.').first.to_sym
93
+ end
89
94
 
90
95
  def get_absolute_paths_for(files)
91
96
  files.map { |file| Pathname.new(file).absolute? ? file : self.root.join('config', file).to_s }
92
97
  end
98
+
99
+ def default_scope?(scope)
100
+ scope.to_s == DEFAULT_SCOPE.to_s
101
+ end
93
102
  end
94
103
  end
@@ -2,6 +2,10 @@ require 'ostruct'
2
2
 
3
3
  module A9n
4
4
  class Struct < OpenStruct
5
+ def empty?
6
+ @table.empty?
7
+ end
8
+
5
9
  def keys
6
10
  @table.keys
7
11
  end
@@ -10,6 +14,16 @@ module A9n
10
14
  @table.fetch(name.to_sym, default)
11
15
  end
12
16
 
17
+ def key?(key)
18
+ to_h.key?(key)
19
+ end
20
+
21
+ def merge(key_value)
22
+ key_value.each_pair do |key, value|
23
+ self[key] = value
24
+ end
25
+ end
26
+
13
27
  def method_missing(name, *args)
14
28
  raise NoSuchConfigurationVariable.new(name)
15
29
  end
@@ -1,3 +1,3 @@
1
1
  module A9n
2
- VERSION = "0.3.4"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -8,6 +8,7 @@ describe A9n do
8
8
  before {
9
9
  subject.app = double(env: env)
10
10
  subject.root = File.expand_path("../../../test_app", __FILE__)
11
+ subject.load
11
12
  }
12
13
 
13
14
  after {
@@ -4,6 +4,7 @@ describe A9n do
4
4
  subject { described_class }
5
5
 
6
6
  after {
7
+ subject.instance_variable_set(:@storage, nil)
7
8
  subject.instance_variable_set(:@env, nil)
8
9
  subject.root = nil
9
10
  subject.app = nil
@@ -105,41 +106,6 @@ describe A9n do
105
106
  it { expect(subject.get_env_var("IS_DWARF")).to be_nil}
106
107
  end
107
108
 
108
- describe ".var_name_for" do
109
- it { expect(subject.var_name_for(:configuration)).to eq(:@configuration) }
110
- it { expect(subject.var_name_for("configuration.yml")).to eq(:@configuration) }
111
- it { expect(subject.var_name_for("custom_dir/extra.yml")).to eq(:@extra) }
112
- end
113
-
114
- describe ".fetch" do
115
- let(:example_config) { A9n::Struct.new({hello: "world"}) }
116
- before {
117
- expect(subject).to receive(:scope).with(subject::DEFAULT_SCOPE).twice.and_return(example_config)
118
- }
119
- it {
120
- expect(subject.fetch(:hello)).to eq("world")
121
- expect(subject.fetch(:wold)).to eq(nil)
122
- }
123
- end
124
-
125
- describe ".scope" do
126
- context "when config has been loaded" do
127
- before {
128
- subject.instance_variable_set(:@custom1, { api_key: '1234asdf'})
129
- expect(subject).to receive(:load).never
130
- }
131
- it {
132
- expect(subject.scope(:custom1)).to eq({ api_key: '1234asdf'})
133
- }
134
- end
135
- context "when config has not been loaded yet" do
136
- it {
137
- expect(subject).to receive(:load)
138
- subject.scope(:custom2)
139
- }
140
- end
141
- end
142
-
143
109
  describe ".default_files" do
144
110
  before {
145
111
  subject.root = File.expand_path("../../../test_app", __FILE__)
@@ -195,4 +161,24 @@ describe A9n do
195
161
  }
196
162
  end
197
163
  end
164
+
165
+ describe ".method_missing" do
166
+ context "when storage is empty" do
167
+ before { expect(subject).to receive(:load).once }
168
+ it {
169
+ expect(subject.storage).to be_empty
170
+ expect { subject.whatever }.to raise_error(A9n::NoSuchConfigurationVariable)
171
+ }
172
+ end
173
+
174
+ context "when storage is not empty" do
175
+ before {
176
+ subject.storage[:whenever] = 'whenever'
177
+ expect(subject).not_to receive(:load)
178
+ }
179
+ it {
180
+ expect { subject.whatever }.to raise_error(A9n::NoSuchConfigurationVariable)
181
+ }
182
+ end
183
+ end
198
184
  end
@@ -1,66 +1,109 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe A9n::Struct do
4
- subject {
5
- described_class.new({
6
- non_empty_dwarf: 'dwarf',
7
- nil_dwarf: nil,
8
- false_dwarf: false,
9
- true_dwarf: true,
10
- hash_dwarf: { dwarf: 'hello' }
11
- })
12
- }
13
-
14
- describe '#keys' do
15
- subject { super().keys }
16
- it { should == [:non_empty_dwarf, :nil_dwarf, :false_dwarf, :true_dwarf, :hash_dwarf] }
17
- end
4
+ context "without any values" do
5
+ subject { described_class.new }
18
6
 
19
- it 'gets non-empty value' do
20
- expect(subject.non_empty_dwarf).to eq('dwarf')
21
- end
7
+ it 'is empty' do
8
+ expect(subject).to be_empty
9
+ end
22
10
 
23
- it 'gets nil value' do
24
- expect(subject.nil_dwarf).to eq(nil)
11
+ it 'raises error' do
12
+ expect {
13
+ subject.dwarf
14
+ }.to raise_error(A9n::NoSuchConfigurationVariable, 'dwarf')
15
+ end
25
16
  end
26
17
 
27
- it 'gets true value' do
28
- expect(subject.true_dwarf).to eq(true)
29
- end
18
+ context "with values" do
19
+ subject {
20
+ described_class.new({
21
+ non_empty_dwarf: 'dwarf',
22
+ nil_dwarf: nil,
23
+ false_dwarf: false,
24
+ true_dwarf: true,
25
+ hash_dwarf: { dwarf: 'hello' }
26
+ })
27
+ }
30
28
 
31
- it 'gets false value' do
32
- expect(subject.false_dwarf).to eq(false)
33
- end
29
+ describe '#keys' do
30
+ subject { super().keys }
34
31
 
35
- it 'gets hash value' do
36
- expect(subject.hash_dwarf).to be_kind_of(Hash)
37
- end
32
+ it do
33
+ expect(subject).to eq [:non_empty_dwarf, :nil_dwarf, :false_dwarf, :true_dwarf, :hash_dwarf]
34
+ end
35
+ end
38
36
 
39
- it 'raises exception when value not exists' do
40
- expect {
41
- subject.non_existing_dwarf
42
- }.to raise_error(A9n::NoSuchConfigurationVariable)
43
- end
37
+ describe '#merge' do
38
+ before { subject.merge(argument) }
39
+
40
+ context 'hash' do
41
+ let(:argument) { { non_empty_dwarf: 'hello dwarf' } }
42
+
43
+ it do
44
+ expect(subject.non_empty_dwarf).to eq('hello dwarf')
45
+ end
46
+ end
47
+
48
+ context 'struct' do
49
+ let(:argument) { described_class.new(non_empty_dwarf: 'hello dwarf') }
44
50
 
45
- describe '#fetch' do
46
- it 'return non empty value' do
47
- expect(subject.fetch(:non_empty_dwarf)).to eq('dwarf')
51
+ it do
52
+ expect(subject.non_empty_dwarf).to eq('hello dwarf')
53
+ end
54
+ end
48
55
  end
49
56
 
50
- it 'return false value' do
51
- expect(subject.fetch(:false_dwarf)).to eq(false)
57
+ it 'is not empty' do
58
+ expect(subject).not_to be_empty
52
59
  end
53
60
 
54
- it 'return nil value' do
55
- expect(subject.fetch(:nil_dwarf)).to eq(nil)
61
+ it 'gets non-empty value' do
62
+ expect(subject.non_empty_dwarf).to eq('dwarf')
56
63
  end
57
64
 
58
- it 'return nil for non existing value' do
59
- expect(subject.fetch(:non_existing_dwarf)).to eq(nil)
65
+ it 'gets nil value' do
66
+ expect(subject.nil_dwarf).to eq(nil)
60
67
  end
61
68
 
62
- it 'return default for non existing value' do
63
- expect(subject.fetch(:non_existing_dwarf, 'default')).to eq('default')
69
+ it 'gets true value' do
70
+ expect(subject.true_dwarf).to eq(true)
71
+ end
72
+
73
+ it 'gets false value' do
74
+ expect(subject.false_dwarf).to eq(false)
75
+ end
76
+
77
+ it 'gets hash value' do
78
+ expect(subject.hash_dwarf).to be_kind_of(Hash)
79
+ end
80
+
81
+ it 'raises exception when value not exists' do
82
+ expect {
83
+ subject.non_existing_dwarf
84
+ }.to raise_error(A9n::NoSuchConfigurationVariable)
85
+ end
86
+
87
+ describe '#fetch' do
88
+ it 'return non empty value' do
89
+ expect(subject.fetch(:non_empty_dwarf)).to eq('dwarf')
90
+ end
91
+
92
+ it 'return false value' do
93
+ expect(subject.fetch(:false_dwarf)).to eq(false)
94
+ end
95
+
96
+ it 'return nil value' do
97
+ expect(subject.fetch(:nil_dwarf)).to eq(nil)
98
+ end
99
+
100
+ it 'return nil for non existing value' do
101
+ expect(subject.fetch(:non_existing_dwarf)).to eq(nil)
102
+ end
103
+
104
+ it 'return default for non existing value' do
105
+ expect(subject.fetch(:non_existing_dwarf, 'default')).to eq('default')
106
+ end
64
107
  end
65
108
  end
66
109
  end
@@ -0,0 +1,29 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'benchmark'
4
+ require 'a9n'
5
+
6
+ class SampleBenchmarkApp
7
+ def run
8
+ 0.upto(1_000).map do |index|
9
+ "#{index} #{::A9n.string_dwarf} #{::A9n.overriden_dwarf}"
10
+ end
11
+ end
12
+
13
+ def root
14
+ Pathname.new('./test_app').expand_path
15
+ end
16
+
17
+ def env
18
+ :test
19
+ end
20
+ end
21
+
22
+ A9n.app = SampleBenchmarkApp.new
23
+ results = []
24
+
25
+ (1..10).each do
26
+ results << Benchmark.realtime { A9n.app.run }
27
+ end
28
+
29
+ puts (results.reduce(&:+) / 10).round(4)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: a9n
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.4
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Krzysztof Knapik
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-14 00:00:00.000000000 Z
11
+ date: 2015-02-17 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: a9n is a tool to keep ruby/rails apps extra configuration easily maintainable
14
14
  and verifiable
@@ -40,6 +40,7 @@ files:
40
40
  - spec/unit/a9n_spec.rb
41
41
  - spec/unit/loader_spec.rb
42
42
  - spec/unit/struct_spec.rb
43
+ - test_app/benchmark.rb
43
44
  - test_app/config/a9n/cloud.yml.erb
44
45
  - test_app/config/a9n/mailer.yml.example
45
46
  - test_app/config/a9n/mandrill.yml