a9n 0.3.0 → 0.3.1

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: e1fa842e61082deb4d82eb3059efed6cb0ce0e50
4
- data.tar.gz: a3250f33bf6df0ae3b06de1bb30774acf958d65f
3
+ metadata.gz: 2c19e68e2155ba1e5eb4b94f13f4345cec6a6550
4
+ data.tar.gz: d49bfe9ff3a925e4117a094b190b57493acc0478
5
5
  SHA512:
6
- metadata.gz: ca996bb79d7331734d27e51eb5b35c1759a95bc680056ca6a25c78ec138d2c6c2272e613cb2bbd18aa4cbb01155ef981d8fa4719f909239abfb3c15c273e9b2a
7
- data.tar.gz: d9e4c62825e16d882d3f9dadb56e4689e64b7036a47b77557208ff9c89a2f5798992fde85eb77fbe26c97d310c35dfd8967b627135497fd18e0f6a1ad0e37841
6
+ metadata.gz: db39e6ebef8b3cbff249bfcd43a57b42fe276886903df28e772ba5f59da862fa8e72d3656b38c98a0f85dc7117c4538dc7d88e00272047cd1473994d877637b6
7
+ data.tar.gz: 18c31604129a4785bac83c6d4d28be8225eff924cb0f1b9ae96c32ccd61fe578d3125f2504087681a05212ea0d9e6d12f45f291009353e8e5f0ac73dd245adf1
@@ -4,3 +4,6 @@ rvm:
4
4
  - 2.0.0
5
5
  - 2.1.2
6
6
  - jruby-19mode
7
+ addons:
8
+ code_climate:
9
+ repo_token: 9aa2aa2432639c57772b6917ad9da468709e5536b75617575b02b35201a2eaf8
data/Gemfile CHANGED
@@ -2,5 +2,5 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
  gem 'rake'
5
- gem 'rspec', '~> 2.14.1'
6
- gem 'coveralls', require: false
5
+ gem 'rspec', '~> 3.0.0'
6
+ gem 'codeclimate-test-reporter', require: false
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2013 Krzysztof Knapik @knapo
1
+ Copyright (c) 2014 Krzysztof Knapik @knapo
2
2
 
3
3
  MIT License
4
4
 
@@ -19,4 +19,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
19
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
20
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
21
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -3,14 +3,16 @@
3
3
  [![Gem Version](https://badge.fury.io/rb/a9n.png)][gem_version]
4
4
  [![Build status](https://secure.travis-ci.org/knapo/a9n.png)][travis]
5
5
  [![Code Climate](https://codeclimate.com/github/knapo/a9n.png)][codeclimate]
6
- [![Coverage Status](https://coveralls.io/repos/knapo/a9n/badge.png?branch=master)][coveralls]
6
+ [![Coverage Status](https://codeclimate.com/github/knapo/a9n/coverage.png)][coverage]
7
7
 
8
8
  [gem_version]: https://rubygems.org/gems/a9n
9
9
  [travis]: http://travis-ci.org/knapo/a9n
10
10
  [codeclimate]: https://codeclimate.com/github/knapo/a9n
11
- [coveralls]: https://coveralls.io/r/knapo/a9n
11
+ [coverage]: https://codeclimate.com/github/knapo/a9n
12
12
 
13
- A9n is a simple tool for managing extra configuration in ruby/rails apps. 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 1.9, 2.0. 2.1. Ruby 1.8 is not supported since version 0.1.2.
14
+
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).
14
16
 
15
17
  ## Installation
16
18
 
@@ -26,9 +28,8 @@ Add `configuration.yml.example` and/or `configuration.yml` file into the config
26
28
  directory. When none fo these files exists, `A9n::MissingConfigurationFile`
27
29
  exception is thrown.
28
30
  If both file exist, content of `configuration.yml` is validated. It means that
29
- all keys existing in example file must exist in base file - in case of missing
30
- keys`A9n::MissingConfigurationVariables` is thrown with information about
31
- missing keys.
31
+ all keys existing in example file must exist in local file - in case of missing
32
+ keys `A9n::MissingConfigurationVariables` is thrown with the explanation what is missing.
32
33
 
33
34
  Set application root and load configuration by adding to your `application.rb` or `environment.rb` right
34
35
  after budler requires:
@@ -36,6 +37,7 @@ after budler requires:
36
37
  A9n.root = File.expand_path('../..', __FILE__)
37
38
  A9n.load
38
39
 
40
+ This step is not required ,if you don't use `a9n` in the environment settings or initializers.
39
41
  It works with `Rails` by default. If you want to use `A9n` with non-rails app
40
42
  you may need to tell that to A9n by:
41
43
 
@@ -60,19 +62,29 @@ is accessible by:
60
62
 
61
63
  ## Custom and multiple configuration files
62
64
 
63
- If you want to scope configuration you may split to multiple files. All files from `config/a9n` are loaded by default, but you may pass custom paths as an argument to `A9n.load` e.g. `A9n.load('lib/facebook/api.yml', 'config/mongoid.yml')`. In such cases config items are accessialbe via scope consistient with the file name.
65
+ If you want to split configuration, you can use multiple files. All files from `config/a9n` are loaded by default, but you may pass custom paths as an argument to `A9n.load` e.g. `A9n.load('config/facebook.yml', 'config/mongoid.yml')`. In such cases config items are accessible through the scope consistent with the file name.
64
66
 
65
67
  E.g. if you have `config/a9n/mandrill.yml`:
66
-
68
+
67
69
  defaults:
68
70
  username: "joe"
69
71
  api_key: "1234asdf"
70
72
 
71
- you can access it by:
73
+ You can access it by:
72
74
 
73
75
  A9n.mandrill.username # => `joe`
74
76
  A9n.mandrill.api_key # => `1234asdf`
75
77
 
78
+
79
+ ## Capistrano
80
+
81
+ If you use capistrano and you feel safe enough to keep all your instance ( staging, production) configuration in the repository, you may find it useful to use capistrano extensions.
82
+ Just add an instance configuration file e.g. `configuration.yml.staging`, `configuration.yml.production` (NOTE: file extension must be consistent with the capistrano stage) and add
83
+
84
+ require 'a9n/capistrano'
85
+
86
+ to your deploy.rb file. This way `configuration.yml.<stage>` overrides `configuration.yml` on each deploy.
87
+
76
88
  ## Contributing
77
89
 
78
90
  1. Fork it
@@ -4,8 +4,8 @@ require File.expand_path('../lib/a9n/version', __FILE__)
4
4
  Gem::Specification.new do |gem|
5
5
  gem.authors = ["Krzysztof Knapik"]
6
6
  gem.email = ["knapo@knapo.net"]
7
- gem.description = %q{Simple tool for managing extra configuration in ruby/rails apps}
8
- gem.summary = %q{a9n is a simple tool for managing extra configuration in ruby/rails apps}
7
+ gem.description = %q{a9n is a tool to keep ruby/rails apps extra configuration easily maintainable and verifiable}
8
+ gem.summary = %q{a9n is a tool to keep ruby/rails apps extra configuration easily maintainable and verifiable}
9
9
  gem.homepage = "https://github.com/knapo/a9n"
10
10
  gem.license = 'MIT'
11
11
  gem.files = `git ls-files`.split($\)
@@ -4,6 +4,8 @@ module A9n
4
4
  class Loader
5
5
  attr_reader :env, :local_file, :example_file
6
6
 
7
+ COMMON_SCOPE = "defaults"
8
+
7
9
  def initialize(file_path, env)
8
10
  @env = env.to_s
9
11
  @local_file = file_path
@@ -15,33 +17,37 @@ module A9n
15
17
  end
16
18
 
17
19
  def load
18
- env_example = self.class.load_yml(example_file, env)
19
- env_local = self.class.load_yml(local_file, env)
20
- default_example = self.class.load_yml(example_file, "defaults")
21
- default_local = self.class.load_yml(local_file, "defaults")
20
+ local_config = self.class.load_yml(local_file, env)
21
+ example_config = self.class.load_yml(example_file, env)
22
22
 
23
- if env_example.nil? && env_local.nil? && default_example.nil? && default_local.nil?
23
+ if local_config.nil? && example_config.nil?
24
24
  raise A9n::MissingConfigurationData.new("Configuration data for *#{env}* env was not found in neither *#{example_file}* nor *#{local_file}*")
25
25
  end
26
26
 
27
- example = A9n::HashExt.merge(default_example, env_example)
28
- local = A9n::HashExt.merge(default_local, env_local)
29
-
30
- if !example.nil? && !local.nil?
31
- verify!(example, local)
27
+ if !local_config.nil? && !example_config.nil?
28
+ verify!(local_config, example_config)
32
29
  end
33
30
 
34
- @struct = A9n::Struct.new(local || example)
31
+ @struct = A9n::Struct.new(local_config || example_config)
35
32
  end
36
33
 
37
- def self.load_yml(file_path, env)
38
- return nil unless File.exists?(file_path)
39
- yml = YAML.load(ERB.new(File.read(file_path)).result)
34
+ class << self
35
+ def load_yml(file_path, env)
36
+ return nil unless File.exists?(file_path)
37
+ yml = YAML.load(ERB.new(File.read(file_path)).result)
38
+
39
+ common_scope = prepare_yml_scope(yml, COMMON_SCOPE)
40
+ env_scope = prepare_yml_scope(yml, env)
41
+
42
+ A9n::HashExt.merge(common_scope, env_scope)
43
+ end
40
44
 
41
- if yml[env].is_a?(::Hash)
42
- A9n::HashExt.deep_symbolize_keys(yml[env])
43
- else
44
- return nil
45
+ def prepare_yml_scope(yml, env_scope)
46
+ if yml[env_scope].is_a?(::Hash)
47
+ A9n::HashExt.deep_symbolize_keys(yml[env_scope])
48
+ else
49
+ nil
50
+ end
45
51
  end
46
52
  end
47
53
 
@@ -1,3 +1,3 @@
1
1
  module A9n
2
- VERSION = "0.3.0"
2
+ VERSION = "0.3.1"
3
3
  end
@@ -1,13 +1,7 @@
1
1
  require 'simplecov'
2
- require 'coveralls'
2
+ require 'codeclimate-test-reporter'
3
3
 
4
- SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
5
- SimpleCov::Formatter::HTMLFormatter,
6
- Coveralls::SimpleCov::Formatter
7
- ]
8
- SimpleCov.start do
9
- add_filter '/spec/'
10
- end
4
+ CodeClimate::TestReporter.start
11
5
 
12
6
  require 'rubygems'
13
7
  require 'bundler/setup'
@@ -15,8 +9,9 @@ require 'bundler/setup'
15
9
  require 'a9n'
16
10
 
17
11
  RSpec.configure do |config|
18
- config.treat_symbols_as_metadata_keys_with_true_values = true
12
+ config.expect_with :rspec do |expect_with|
13
+ expect_with.syntax = :expect
14
+ end
19
15
  config.order = "random"
20
- config.color_enabled = true
21
16
  config.tty = true
22
17
  end
@@ -13,18 +13,12 @@ describe A9n::Loader do
13
13
  end
14
14
 
15
15
  describe "#load" do
16
- let(:example_env_config) {
17
- { app_url: "http://127.0.0.1:3000", api_key: "base1234" }
16
+ let(:example_config) {
17
+ { app_url: "http://127.0.0.1:3000", api_key: "example1234" }
18
18
  }
19
- let(:local_env_config) {
19
+ let(:local_config) {
20
20
  { app_host: "127.0.0.1:3000", api_key: "local1234" }
21
21
  }
22
- let(:example_default_config) {
23
- { page_title: "Base Kielbasa", api_key: "example1234default" }
24
- }
25
- let(:local_default_config) {
26
- { page_title: "Local Kielbasa", api_key: "local1234default" }
27
- }
28
22
  let(:env){
29
23
  "tropical"
30
24
  }
@@ -34,8 +28,6 @@ describe A9n::Loader do
34
28
  before do
35
29
  expect(described_class).to receive(:load_yml).with(subject.example_file, env).and_return(nil)
36
30
  expect(described_class).to receive(:load_yml).with(subject.local_file, env).and_return(nil)
37
- expect(described_class).to receive(:load_yml).with(subject.example_file, "defaults").and_return(nil)
38
- expect(described_class).to receive(:load_yml).with(subject.local_file, "defaults").and_return(nil)
39
31
  expect(subject).to receive(:verify!).never
40
32
  end
41
33
  it "raises expection" do
@@ -45,37 +37,30 @@ describe A9n::Loader do
45
37
  end
46
38
  end
47
39
 
48
- context "when example configuration file exists with defaults" do
40
+ context "when only example configuration file exists" do
49
41
  before do
50
- expect(described_class).to receive(:load_yml).with(subject.example_file, env).and_return(example_env_config)
42
+ expect(described_class).to receive(:load_yml).with(subject.example_file, env).and_return(example_config)
51
43
  expect(described_class).to receive(:load_yml).with(subject.local_file, env).and_return(nil)
52
- expect(described_class).to receive(:load_yml).with(subject.example_file, "defaults").and_return(example_default_config)
53
- expect(described_class).to receive(:load_yml).with(subject.local_file, "defaults").and_return(nil)
54
-
55
44
  expect(described_class).to receive(:verify!).never
56
45
  subject.load
57
46
  end
58
47
 
59
48
  it { expect(config.app_url).to eq("http://127.0.0.1:3000") }
60
- it { expect(config.page_title).to eq("Base Kielbasa") }
61
- it { expect(config.api_key).to eq("base1234") }
49
+ it { expect(config.api_key).to eq("example1234") }
62
50
 
63
51
  it {
64
52
  expect { config.app_host }.to raise_error(A9n::NoSuchConfigurationVariable)
65
53
  }
66
54
  end
67
55
 
68
- context "when local configuration file exists with defaults" do
56
+ context "when only local configuration file exists" do
69
57
  before do
70
58
  expect(described_class).to receive(:load_yml).with(subject.example_file, env).and_return(nil)
71
- expect(described_class).to receive(:load_yml).with(subject.local_file, env).and_return(local_env_config)
72
- expect(described_class).to receive(:load_yml).with(subject.example_file, "defaults").and_return(nil)
73
- expect(described_class).to receive(:load_yml).with(subject.local_file, "defaults").and_return(local_default_config)
59
+ expect(described_class).to receive(:load_yml).with(subject.local_file, env).and_return(local_config)
74
60
  expect(described_class).to receive(:verify!).never
75
61
  subject.load
76
62
  end
77
63
  it { expect(config.app_host).to eq("127.0.0.1:3000") }
78
- it { expect(config.page_title).to eq("Local Kielbasa") }
79
64
  it { expect(config.api_key).to eq("local1234") }
80
65
 
81
66
  it {
@@ -86,19 +71,14 @@ describe A9n::Loader do
86
71
  context "when both local and base configuration file exists without defaults" do
87
72
  context "with same data" do
88
73
  before do
89
- expect(described_class).to receive(:load_yml).with(subject.example_file, env).and_return(example_env_config)
90
- expect(described_class).to receive(:load_yml).with(subject.local_file, env).and_return(example_env_config)
91
- expect(described_class).to receive(:load_yml).with(subject.example_file, "defaults").and_return(nil)
92
- expect(described_class).to receive(:load_yml).with(subject.local_file, "defaults").and_return(nil)
74
+ expect(described_class).to receive(:load_yml).with(subject.example_file, env).and_return(example_config)
75
+ expect(described_class).to receive(:load_yml).with(subject.local_file, env).and_return(example_config)
93
76
  subject.load
94
77
  end
95
78
 
96
79
  it { expect(config.app_url).to eq("http://127.0.0.1:3000") }
97
- it { expect(config.api_key).to eq("base1234") }
80
+ it { expect(config.api_key).to eq("example1234") }
98
81
 
99
- it {
100
- expect { config.page_title }.to raise_error(A9n::NoSuchConfigurationVariable)
101
- }
102
82
  it {
103
83
  expect { config.app_host }.to raise_error(A9n::NoSuchConfigurationVariable)
104
84
  }
@@ -106,10 +86,8 @@ describe A9n::Loader do
106
86
 
107
87
  context "with different data" do
108
88
  before do
109
- expect(described_class).to receive(:load_yml).with(subject.example_file, env).and_return(example_env_config)
110
- expect(described_class).to receive(:load_yml).with(subject.local_file, env).and_return(local_env_config)
111
- expect(described_class).to receive(:load_yml).with(subject.example_file, "defaults").and_return(nil)
112
- expect(described_class).to receive(:load_yml).with(subject.local_file, "defaults").and_return(nil)
89
+ expect(described_class).to receive(:load_yml).with(subject.example_file, env).and_return(example_config)
90
+ expect(described_class).to receive(:load_yml).with(subject.local_file, env).and_return(local_config)
113
91
  end
114
92
  it "raises expection" do
115
93
  expect {
@@ -125,22 +103,31 @@ describe A9n::Loader do
125
103
  subject { described_class.load_yml(file_path, env) }
126
104
 
127
105
  context "when file not exists" do
128
- let(:file_path) { "file_not_existing_in_universe.yml" }
106
+ let(:file_path) { "file_not_existing_in_the_universe.yml" }
129
107
 
130
108
  it{ expect(subject).to be_nil }
131
109
  end
132
110
 
133
111
  context "when file exists" do
134
- let(:file_path) { File.join(root, "config/configuration.yml") }
112
+ shared_examples "non-empty config file" do
113
+ it "returns non-empty hash" do
114
+ expect(subject).to be_kind_of(Hash)
115
+ expect(subject.keys).to_not be_empty
116
+ end
117
+ end
135
118
 
136
119
  before {
137
120
  ENV["DWARF"] = "erbized dwarf"
138
121
  }
139
122
 
140
- context "and has data" do
141
- it "returns non-empty hash" do
142
- expect(subject).to be_kind_of(Hash)
143
- expect(subject.keys).to_not be_empty
123
+ context "having env and defaults data" do
124
+ let(:file_path) { File.join(root, "config/configuration.yml") }
125
+
126
+ it_behaves_like "non-empty config file"
127
+
128
+ it "contains keys from defaults scope" do
129
+ expect(subject[:default_dwarf]).to eq("default dwarf")
130
+ expect(subject[:overriden_dwarf]).to eq("already overriden dwarf")
144
131
  end
145
132
 
146
133
  it "has symbolized keys" do
@@ -154,9 +141,30 @@ describe A9n::Loader do
154
141
  end
155
142
  end
156
143
 
157
- context "and has no data" do
144
+ context "having no env and only defaults data" do
145
+ let(:file_path) { File.join(root, "config/configuration.yml") }
158
146
  let(:env) { "production" }
159
- it{ expect(subject).to be_nil }
147
+
148
+ it_behaves_like "non-empty config file"
149
+
150
+ it "contains keys from defaults scope" do
151
+ expect(subject[:default_dwarf]).to eq("default dwarf")
152
+ expect(subject[:overriden_dwarf]).to eq("not yet overriden dwarf")
153
+ end
154
+ end
155
+
156
+ context "having only env and no default data" do
157
+ let(:file_path) { File.join(root, "config/no_defaults.yml") }
158
+
159
+ context "valid env" do
160
+ let(:env) { "production" }
161
+ it_behaves_like "non-empty config file"
162
+ end
163
+
164
+ context "invalid env" do
165
+ let(:env) { "tropical" }
166
+ it { expect(subject).to be_nil }
167
+ end
160
168
  end
161
169
  end
162
170
  end
@@ -0,0 +1,3 @@
1
+ production:
2
+ username: "joe"
3
+ api_key: "asdf1234"
metadata CHANGED
@@ -1,16 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: a9n
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Krzysztof Knapik
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-05-29 00:00:00.000000000 Z
11
+ date: 2014-07-25 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: Simple tool for managing extra configuration in ruby/rails apps
13
+ description: a9n is a tool to keep ruby/rails apps extra configuration easily maintainable
14
+ and verifiable
14
15
  email:
15
16
  - knapo@knapo.net
16
17
  executables: []
@@ -39,6 +40,7 @@ files:
39
40
  - test_app/config/a9n/mandrill.yml
40
41
  - test_app/config/configuration.yml
41
42
  - test_app/config/configuration.yml.example
43
+ - test_app/config/no_defaults.yml
42
44
  homepage: https://github.com/knapo/a9n
43
45
  licenses:
44
46
  - MIT
@@ -62,7 +64,8 @@ rubyforge_project:
62
64
  rubygems_version: 2.2.2
63
65
  signing_key:
64
66
  specification_version: 4
65
- summary: a9n is a simple tool for managing extra configuration in ruby/rails apps
67
+ summary: a9n is a tool to keep ruby/rails apps extra configuration easily maintainable
68
+ and verifiable
66
69
  test_files:
67
70
  - spec/integration/a9n_spec.rb
68
71
  - spec/spec_helper.rb