omniconf 0.0.1 → 0.0.2
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.
- data/.travis.yml +1 -1
- data/README.md +28 -18
- data/lib/omniconf/adapters/active_record.rb +6 -5
- data/lib/omniconf/adapters/base.rb +1 -0
- data/lib/omniconf/adapters/yaml.rb +1 -0
- data/lib/omniconf/configuration.rb +8 -3
- data/lib/omniconf/version.rb +1 -1
- data/lib/omniconf.rb +4 -5
- data/lib/rails/generators/omniconf/install/install_generator.rb +29 -0
- data/lib/rails/generators/omniconf/install/templates/migrations/1_create_config_values.rb +9 -0
- data/lib/rails/generators/omniconf/install/templates/omniconf.rb.erb +13 -0
- data/spec/fixtures/omniconf/adapters/yaml/config/settings.yml +3 -0
- data/spec/omniconf/adapters/active_record_spec.rb +34 -21
- data/spec/omniconf/adapters/yaml_spec.rb +28 -19
- data/spec/omniconf_spec.rb +4 -2
- metadata +14 -11
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -4,18 +4,21 @@ A _RubyGem_ that provides an application-agnostic configuration merger.
|
|
4
4
|
|
5
5
|
# Setup
|
6
6
|
|
7
|
-
Configure and load desired
|
7
|
+
Configure and load desired back-ends by creating a new initializer:
|
8
|
+
|
9
|
+
- With a Rails application, just run `rails g omniconf:install`.
|
10
|
+
- Without a Rails application, you need to create a file along these lines (see below):
|
8
11
|
|
9
12
|
```ruby
|
10
13
|
Omniconf.setup do |config|
|
11
14
|
config.sources = {
|
12
|
-
:
|
15
|
+
:yaml => {
|
13
16
|
:type => :yaml,
|
14
17
|
:file => "config/settings.yml"
|
15
18
|
},
|
16
|
-
:
|
19
|
+
:database => {
|
17
20
|
:type => :active_record,
|
18
|
-
:
|
21
|
+
:model => "ConfigValue"
|
19
22
|
}
|
20
23
|
}
|
21
24
|
end
|
@@ -44,13 +47,13 @@ $ rails c
|
|
44
47
|
```ruby
|
45
48
|
> Omniconf.configuration.some_config_from_database = "def" # updates value in DB using ConfigValue model
|
46
49
|
=> "def"
|
47
|
-
> Omniconf.configuration.some_config_from_yaml = 456 # raises an exception because the value comes from YAML
|
48
|
-
=> Omniconf::ReadOnlyConfigurationValue: cannot set 'some_config_from_yaml' because it belongs to a read-only back-end source (id: :
|
50
|
+
> Omniconf.configuration.some_config_from_yaml = 456 # raises an exception because the value comes from YAML
|
51
|
+
=> Omniconf::ReadOnlyConfigurationValue: cannot set 'some_config_from_yaml' because it belongs to a read-only back-end source (id: :yaml, type: Yaml)
|
49
52
|
> Omniconf.configuration.api.username = "admin" # it works with nested values too
|
50
53
|
=> "admin"
|
51
54
|
> Omniconf.configuration.brand_new_value = "whatever" # raises an exception because you've got to tell which back-end will store the new value
|
52
55
|
=> Omniconf::UnknownConfigurationValue: cannot set a configuration value with no parent
|
53
|
-
> Omniconf.sources[:
|
56
|
+
> Omniconf.sources[:database].brand_new_value = "whatever" # adds a new record in ConfigValue model
|
54
57
|
=> "whatever"
|
55
58
|
```
|
56
59
|
|
@@ -61,15 +64,21 @@ Other parameters default to standard values for Rails.
|
|
61
64
|
|
62
65
|
### Yaml
|
63
66
|
|
64
|
-
Nothing to configure apart from having a YAML file.
|
65
|
-
|
66
67
|
_Note: read-only._
|
67
68
|
|
69
|
+
#### Parameters
|
70
|
+
|
71
|
+
- `:type => :yaml`
|
72
|
+
- `:file`: path to the YAML file to load (default: `config/settings.yml`)
|
73
|
+
- `:environment`: the root node to load from your YAML file (typically `development`, `production`, etc.)
|
74
|
+
|
68
75
|
### ActiveRecord
|
69
76
|
|
70
|
-
|
77
|
+
#### Setup
|
71
78
|
|
72
|
-
|
79
|
+
- Add `gem 'activerecord'` in your `Gemfile`.
|
80
|
+
- With a Rails application, `rails g omniconf:install` has already created a migration for you.
|
81
|
+
- Without a Rails application, create a new migration to add the config table:
|
73
82
|
|
74
83
|
```ruby
|
75
84
|
class CreateConfigValues < ActiveRecord::Migration
|
@@ -83,19 +92,20 @@ class CreateConfigValues < ActiveRecord::Migration
|
|
83
92
|
end
|
84
93
|
```
|
85
94
|
|
86
|
-
|
87
|
-
|
88
|
-
Add `gem 'redis'` in your `Gemfile`.
|
95
|
+
#### Parameters
|
89
96
|
|
90
|
-
|
97
|
+
- `:type => :active_record`
|
98
|
+
- `:model`: name of the ActiveRecord model (default: `ConfigValue`)
|
99
|
+
- `:config_file`: path to the database settings (default: `config/database.yml`)
|
100
|
+
- `:environment`: environment to load (typically `development`, `production`, etc.)
|
91
101
|
|
92
102
|
## Reserved words
|
93
103
|
|
94
104
|
/!\ You should not use these names as configuration keys:
|
95
105
|
|
96
|
-
- `to_hash`:
|
106
|
+
- `to_hash`: returns the configuration as a hash
|
97
107
|
- `inspect`: outputs sub-values as a hash
|
98
|
-
- `get_or_default`:
|
108
|
+
- `get_or_default`: returns the value if it exists or creates it otherwise (usage: `get_or_default(key, default_value)`)
|
99
109
|
- `method_missing`: used internally
|
100
110
|
- everything which starts with `__` (double underscore): used internally
|
101
111
|
|
@@ -103,7 +113,7 @@ Not yet implemented.
|
|
103
113
|
|
104
114
|
`rake`
|
105
115
|
|
106
|
-
Tested against _ree_, _ruby-1.9.
|
116
|
+
Tested against _ree_, _ruby-1.9.2_ and _ruby-1.9.3_ thanks to [Travis CI](http://travis-ci.org/#!/Picklive/omniconf "It rocks!").
|
107
117
|
|
108
118
|
# License
|
109
119
|
|
@@ -6,7 +6,7 @@ module Omniconf
|
|
6
6
|
def initialize id, params
|
7
7
|
@source_id = id
|
8
8
|
defaults = {
|
9
|
-
:
|
9
|
+
:model => 'ConfigValue'
|
10
10
|
}
|
11
11
|
defaults.merge!({
|
12
12
|
:environment => Rails.env,
|
@@ -24,7 +24,7 @@ module Omniconf
|
|
24
24
|
begin
|
25
25
|
records = @model.all
|
26
26
|
rescue ::ActiveRecord::StatementInvalid => e
|
27
|
-
Omniconf.logger.warn "Could not load #{@params[:
|
27
|
+
Omniconf.logger.warn "Could not load #{@params[:model]} model, ignoring this configuration source."
|
28
28
|
return
|
29
29
|
end
|
30
30
|
|
@@ -54,7 +54,7 @@ module Omniconf
|
|
54
54
|
|
55
55
|
def setup
|
56
56
|
# define the ActiveRecord model if missing
|
57
|
-
unless Object.const_defined? @params[:
|
57
|
+
unless Object.const_defined? @params[:model]
|
58
58
|
unless ::ActiveRecord::Base.connected?
|
59
59
|
::ActiveRecord::Base.configurations = YAML::load(IO.read(@params[:config_file]))
|
60
60
|
::ActiveRecord::Base.establish_connection(@params[:environment])
|
@@ -62,12 +62,13 @@ module Omniconf
|
|
62
62
|
|
63
63
|
klass = Class.new ::ActiveRecord::Base do
|
64
64
|
validates_uniqueness_of :key
|
65
|
+
serialize :value
|
65
66
|
end
|
66
67
|
|
67
|
-
Object.const_set @params[:
|
68
|
+
Object.const_set @params[:model], klass
|
68
69
|
end
|
69
70
|
|
70
|
-
@model ||= @params[:
|
71
|
+
@model ||= @params[:model].constantize
|
71
72
|
end
|
72
73
|
end
|
73
74
|
end
|
@@ -67,9 +67,14 @@ module Omniconf
|
|
67
67
|
# add a catch-all exception
|
68
68
|
# (more descriptive than "undefined method `xxx' for nil:NilClass")
|
69
69
|
class << value
|
70
|
-
def method_missing *args
|
71
|
-
|
72
|
-
|
70
|
+
def method_missing method, *args
|
71
|
+
if method == :to_str
|
72
|
+
# need to raise NoMethodError here for Ruby 1.9.2 compatibility
|
73
|
+
raise NoMethodError, "undefined method `#{method}' for #{self}"
|
74
|
+
else
|
75
|
+
raise UnknownConfigurationValue,
|
76
|
+
"cannot get a configuration value with no parent"
|
77
|
+
end
|
73
78
|
end
|
74
79
|
end
|
75
80
|
end
|
data/lib/omniconf/version.rb
CHANGED
data/lib/omniconf.rb
CHANGED
@@ -22,11 +22,10 @@ module Omniconf
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def logger
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
25
|
+
return @logger ||= Rails.logger if defined? Rails
|
26
|
+
|
27
|
+
@logger ||= Logger.new(STDOUT)
|
28
|
+
@logger.level = @settings.logger_level || Logger::INFO
|
30
29
|
@logger
|
31
30
|
end
|
32
31
|
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Omniconf
|
2
|
+
module Generators
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
desc "Installs Omniconf and generates the necessary migration"
|
5
|
+
|
6
|
+
include Rails::Generators::Migration
|
7
|
+
|
8
|
+
def self.source_root
|
9
|
+
File.expand_path("../templates", __FILE__)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.next_migration_number(dirname)
|
13
|
+
Time.now.strftime("%Y%m%d%H%M%S")
|
14
|
+
end
|
15
|
+
|
16
|
+
def copy_initializer
|
17
|
+
template 'omniconf.rb.erb', 'config/initializers/omniconf.rb'
|
18
|
+
end
|
19
|
+
|
20
|
+
def create_migrations
|
21
|
+
Dir["#{self.class.source_root}/migrations/*.rb"].sort.each do |filepath|
|
22
|
+
name = File.basename(filepath)
|
23
|
+
migration_template "migrations/#{name}", "db/migrate/#{name.gsub(/^\d+_/,'')}"
|
24
|
+
sleep 1 # ensure next migration gets a new number
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -4,7 +4,7 @@ require 'omniconf/adapters/active_record'
|
|
4
4
|
describe Omniconf::Adapter::ActiveRecord do
|
5
5
|
def load_configuration
|
6
6
|
@adapter = Omniconf::Adapter::ActiveRecord.new(:active_record, {
|
7
|
-
:
|
7
|
+
:model => 'ConfigValue',
|
8
8
|
:environment => 'test',
|
9
9
|
:config_file => File.expand_path(
|
10
10
|
'../../../fixtures/omniconf/adapters/active_record/config/database.yml',
|
@@ -21,54 +21,67 @@ describe Omniconf::Adapter::ActiveRecord do
|
|
21
21
|
end
|
22
22
|
|
23
23
|
describe "#configuration" do
|
24
|
+
def config
|
25
|
+
@adapter.configuration
|
26
|
+
end
|
27
|
+
|
24
28
|
before do
|
25
29
|
Omniconf.stub(:merge_configuration!)
|
26
30
|
load_configuration
|
27
31
|
end
|
28
32
|
|
29
|
-
let(:configuration) { @adapter.configuration }
|
30
|
-
|
31
33
|
describe "getting values" do
|
32
34
|
it "returns a value" do
|
33
|
-
|
35
|
+
config.ar_key.should == 'ar_value'
|
34
36
|
end
|
35
37
|
|
36
38
|
it "returns a nested value" do
|
37
|
-
|
39
|
+
config.nested.ar_key.should == 'nested_ar_value'
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
41
43
|
describe "setting values" do
|
42
|
-
it "updates
|
43
|
-
|
44
|
-
|
45
|
-
|
44
|
+
it "updates config values into database" do
|
45
|
+
config.ar_key.should == 'ar_value'
|
46
|
+
config.ar_key = 'new_ar_value'
|
47
|
+
config.ar_key.should == 'new_ar_value'
|
46
48
|
end
|
47
49
|
|
48
|
-
it "creates
|
49
|
-
|
50
|
-
|
51
|
-
|
50
|
+
it "creates config values into database" do
|
51
|
+
config.new_ar_key.should be_nil
|
52
|
+
config.new_ar_key = 'new_ar_value'
|
53
|
+
config.new_ar_key.should == 'new_ar_value'
|
52
54
|
end
|
53
|
-
|
54
|
-
it "it doesn't cast values to String" # TODO serialize them and keep type
|
55
55
|
end
|
56
56
|
|
57
57
|
describe "#get_or_default" do
|
58
58
|
it "creates a new default value" do
|
59
|
-
|
59
|
+
config.newValue.should be_nil
|
60
60
|
@adapter.should_receive(:set_value).with(['newValue'], 'a')
|
61
|
-
|
62
|
-
|
61
|
+
config.get_or_default('newValue', 'a').should == 'a'
|
62
|
+
config.get_or_default('newValue', 'b').should == 'a'
|
63
63
|
end
|
64
64
|
|
65
65
|
it "creates a new default nested value" do
|
66
|
-
|
66
|
+
config.nested.newValue.should be_nil
|
67
67
|
@adapter.should_receive(:set_value).with(['nested', 'newValue'], 'a')
|
68
|
-
|
69
|
-
|
68
|
+
config.nested.get_or_default('newValue', 'a').should == 'a'
|
69
|
+
config.nested.get_or_default('newValue', 'b').should == 'a'
|
70
70
|
end
|
71
71
|
end
|
72
|
+
|
73
|
+
it "keeps value types" do
|
74
|
+
config.some_integer.should be_nil
|
75
|
+
config.some_float.should be_nil
|
76
|
+
config.some_array.should be_nil
|
77
|
+
config.some_integer = 1337
|
78
|
+
config.some_float = 3.14
|
79
|
+
config.some_array = [1, 2, 3]
|
80
|
+
@adapter.reload_configuration!
|
81
|
+
config.some_integer.should == 1337
|
82
|
+
config.some_float.should == 3.14
|
83
|
+
config.some_array.should == [1, 2, 3]
|
84
|
+
end
|
72
85
|
end
|
73
86
|
end
|
74
87
|
|
@@ -12,75 +12,84 @@ describe Omniconf::Adapter::Yaml do
|
|
12
12
|
@adapter.load_configuration!
|
13
13
|
end
|
14
14
|
|
15
|
+
|
15
16
|
describe "#configuration" do
|
17
|
+
def config
|
18
|
+
@adapter.configuration
|
19
|
+
end
|
20
|
+
|
16
21
|
before do
|
17
22
|
Omniconf.stub(:merge_configuration!)
|
18
23
|
load_configuration('test')
|
19
24
|
end
|
20
25
|
|
21
|
-
let(:configuration) { @adapter.configuration }
|
22
|
-
|
23
26
|
describe "getting values" do
|
24
27
|
it "returns a value" do
|
25
|
-
|
28
|
+
config.yaml_key.should == 'yaml_value'
|
26
29
|
end
|
27
30
|
|
28
31
|
it "returns a nested value" do
|
29
|
-
|
32
|
+
config.nested.yaml_key.should == 'nested_yaml_value'
|
30
33
|
end
|
31
34
|
end
|
32
35
|
|
33
36
|
describe "setting values" do
|
34
37
|
it "fails to update a value" do
|
35
|
-
|
38
|
+
config.yaml_key.should_not be_nil
|
36
39
|
expect {
|
37
|
-
|
40
|
+
config.yaml_key = 'whatever'
|
38
41
|
}.to raise_error Omniconf::ReadOnlyConfigurationValue
|
39
42
|
end
|
40
43
|
|
41
44
|
it "fails to update a nested value" do
|
42
|
-
|
45
|
+
config.nested.yaml_key.should_not be_nil
|
43
46
|
expect {
|
44
|
-
|
47
|
+
config.nested.yaml_key = 'whatever'
|
45
48
|
}.to raise_error Omniconf::ReadOnlyConfigurationValue
|
46
49
|
end
|
47
50
|
|
48
51
|
it "fails to create a value" do
|
49
|
-
|
52
|
+
config.new_yaml_key.should be_nil
|
50
53
|
expect {
|
51
|
-
|
54
|
+
config.new_yaml_key = 'whatever'
|
52
55
|
}.to raise_error Omniconf::ReadOnlyConfigurationValue
|
53
56
|
end
|
54
57
|
|
55
58
|
it "fails to create a nested value" do
|
56
|
-
|
59
|
+
config.nested.new_yaml_key.should be_nil
|
57
60
|
expect {
|
58
|
-
|
61
|
+
config.nested.new_yaml_key = 'whatever'
|
59
62
|
}.to raise_error Omniconf::ReadOnlyConfigurationValue
|
60
63
|
end
|
61
64
|
end
|
62
65
|
|
63
66
|
describe "#get_or_default" do
|
64
67
|
it "fails to create a new default value" do
|
65
|
-
|
68
|
+
config.newValue.should be_nil
|
66
69
|
expect {
|
67
|
-
|
70
|
+
config.get_or_default('newValue', 'a').should == 'a'
|
68
71
|
}.to raise_error Omniconf::ReadOnlyConfigurationValue
|
69
|
-
|
72
|
+
config.newValue.should be_nil
|
70
73
|
end
|
71
74
|
|
72
75
|
it "fails to create a new nested default value" do
|
73
|
-
|
76
|
+
config.nested.newValue.should be_nil
|
74
77
|
expect {
|
75
|
-
|
78
|
+
config.nested.get_or_default('newValue', 'a').should == 'a'
|
76
79
|
}.to raise_error Omniconf::ReadOnlyConfigurationValue
|
77
|
-
|
80
|
+
config.nested.newValue.should be_nil
|
78
81
|
end
|
79
82
|
end
|
80
83
|
|
81
84
|
it "loads the right environment" do
|
82
85
|
load_configuration 'development'
|
83
|
-
|
86
|
+
config.yaml_key.should == 'yaml_value_dev'
|
87
|
+
end
|
88
|
+
|
89
|
+
it "keeps value types" do
|
90
|
+
config.some_integer.should == 1337
|
91
|
+
config.some_float.should == 3.14
|
92
|
+
config.some_array.should == [1, 2, 3]
|
84
93
|
end
|
85
94
|
end
|
86
95
|
end
|
data/spec/omniconf_spec.rb
CHANGED
@@ -30,7 +30,7 @@ describe Omniconf do
|
|
30
30
|
},
|
31
31
|
:database => {
|
32
32
|
:type => :active_record,
|
33
|
-
:
|
33
|
+
:model => 'ConfigValue',
|
34
34
|
:environment => 'test',
|
35
35
|
:config_file => File.expand_path(
|
36
36
|
'../fixtures/omniconf/adapters/active_record/config/database.yml',
|
@@ -49,7 +49,9 @@ describe Omniconf do
|
|
49
49
|
end
|
50
50
|
|
51
51
|
describe "#configuration" do
|
52
|
-
|
52
|
+
def config
|
53
|
+
Omniconf.configuration
|
54
|
+
end
|
53
55
|
|
54
56
|
it "returns an instance of Omniconf::Configuration" do
|
55
57
|
config.should be_an_instance_of Omniconf::Configuration
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: omniconf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-02-
|
12
|
+
date: 2012-02-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
16
|
-
requirement: &
|
16
|
+
requirement: &2152356800 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0.9'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *2152356800
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rspec
|
27
|
-
requirement: &
|
27
|
+
requirement: &2152342400 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '2.8'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *2152342400
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: sqlite3
|
38
|
-
requirement: &
|
38
|
+
requirement: &2152340720 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '1.3'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *2152340720
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: activerecord
|
49
|
-
requirement: &
|
49
|
+
requirement: &2152339860 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
@@ -54,7 +54,7 @@ dependencies:
|
|
54
54
|
version: '3.2'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *2152339860
|
58
58
|
description: Merge configurations from multiple back-ends for easy use in a complex
|
59
59
|
application.
|
60
60
|
email:
|
@@ -82,6 +82,9 @@ files:
|
|
82
82
|
- lib/omniconf/helpers.rb
|
83
83
|
- lib/omniconf/settings.rb
|
84
84
|
- lib/omniconf/version.rb
|
85
|
+
- lib/rails/generators/omniconf/install/install_generator.rb
|
86
|
+
- lib/rails/generators/omniconf/install/templates/migrations/1_create_config_values.rb
|
87
|
+
- lib/rails/generators/omniconf/install/templates/omniconf.rb.erb
|
85
88
|
- omniconf.gemspec
|
86
89
|
- spec/fixtures/omniconf/adapters/active_record/config/database.yml
|
87
90
|
- spec/fixtures/omniconf/adapters/active_record/db/schema.rb
|
@@ -112,7 +115,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
112
115
|
version: '0'
|
113
116
|
requirements: []
|
114
117
|
rubyforge_project: omniconf
|
115
|
-
rubygems_version: 1.8.
|
118
|
+
rubygems_version: 1.8.10
|
116
119
|
signing_key:
|
117
120
|
specification_version: 3
|
118
121
|
summary: Merge multiple configuration sources into one.
|