a9n 0.3.0 → 0.3.1
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 +4 -4
- data/.travis.yml +3 -0
- data/Gemfile +2 -2
- data/LICENSE +2 -2
- data/README.md +21 -9
- data/a9n.gemspec +2 -2
- data/lib/a9n/loader.rb +24 -18
- data/lib/a9n/version.rb +1 -1
- data/spec/spec_helper.rb +5 -10
- data/spec/unit/loader_spec.rb +51 -43
- data/test_app/config/no_defaults.yml +3 -0
- metadata +7 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2c19e68e2155ba1e5eb4b94f13f4345cec6a6550
|
|
4
|
+
data.tar.gz: d49bfe9ff3a925e4117a094b190b57493acc0478
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: db39e6ebef8b3cbff249bfcd43a57b42fe276886903df28e772ba5f59da862fa8e72d3656b38c98a0f85dc7117c4538dc7d88e00272047cd1473994d877637b6
|
|
7
|
+
data.tar.gz: 18c31604129a4785bac83c6d4d28be8225eff924cb0f1b9ae96c32ccd61fe578d3125f2504087681a05212ea0d9e6d12f45f291009353e8e5f0ac73dd245adf1
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/LICENSE
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Copyright (c)
|
|
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]
|
|
4
4
|
[][travis]
|
|
5
5
|
[][codeclimate]
|
|
6
|
-
[][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
|
-
[
|
|
11
|
+
[coverage]: https://codeclimate.com/github/knapo/a9n
|
|
12
12
|
|
|
13
|
-
A9n is a simple tool
|
|
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
|
|
30
|
-
keys`A9n::MissingConfigurationVariables` is thrown with
|
|
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
|
|
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
|
-
|
|
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
|
data/a9n.gemspec
CHANGED
|
@@ -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{
|
|
8
|
-
gem.summary = %q{a9n is a
|
|
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($\)
|
data/lib/a9n/loader.rb
CHANGED
|
@@ -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
|
-
|
|
19
|
-
|
|
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
|
|
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
|
-
|
|
28
|
-
|
|
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(
|
|
31
|
+
@struct = A9n::Struct.new(local_config || example_config)
|
|
35
32
|
end
|
|
36
33
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
|
data/lib/a9n/version.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
require 'simplecov'
|
|
2
|
-
require '
|
|
2
|
+
require 'codeclimate-test-reporter'
|
|
3
3
|
|
|
4
|
-
|
|
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.
|
|
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
|
data/spec/unit/loader_spec.rb
CHANGED
|
@@ -13,18 +13,12 @@ describe A9n::Loader do
|
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
describe "#load" do
|
|
16
|
-
let(:
|
|
17
|
-
{ app_url: "http://127.0.0.1:3000", api_key: "
|
|
16
|
+
let(:example_config) {
|
|
17
|
+
{ app_url: "http://127.0.0.1:3000", api_key: "example1234" }
|
|
18
18
|
}
|
|
19
|
-
let(:
|
|
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
|
|
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(
|
|
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.
|
|
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
|
|
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(
|
|
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(
|
|
90
|
-
expect(described_class).to receive(:load_yml).with(subject.local_file, env).and_return(
|
|
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("
|
|
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(
|
|
110
|
-
expect(described_class).to receive(:load_yml).with(subject.local_file, env).and_return(
|
|
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) { "
|
|
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
|
-
|
|
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
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
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
|
|
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
|
-
|
|
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
|
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.
|
|
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-
|
|
11
|
+
date: 2014-07-25 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
|
-
description:
|
|
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
|
|
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
|