dacs 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,10 @@
1
+ == 0.3.0 2010-01-14
2
+ * Minor enhancements
3
+ * When an explicit schema is defined (using DSL):
4
+ * Will warn and exit when required keys are not configured
5
+ * Will raise an error when an undefined key is referenced
6
+ * New #report method added to dump a full configuration report
7
+
1
8
  == 0.2.0 2010-01-13
2
9
  * Major enhancements
3
10
  * Added new mini-DSL for defining known configuration keys
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.3.0
data/example/example.rb CHANGED
@@ -17,9 +17,10 @@ puts "foo: #{Dacs::AppConfig['foo']}"
17
17
  puts "bar: #{Dacs::AppConfig['bar']}"
18
18
  puts "baz: #{Dacs::AppConfig['baz']}"
19
19
  puts Dacs::AppConfig.dump # => nil
20
+ puts Dacs::AppConfig.report # => nil
20
21
 
21
- # >> I, [2010-02-13T02:34:46.344705 #25573] INFO -- : Found config file /devver-repos/dacs/example/example.yml.
22
- # >> W, [2010-02-13T02:34:46.345300 #25573] WARN -- : Unknown configuration key 'fuz' in file example.yml
22
+ # >> I, [2010-02-14T09:45:52.703585 #17437] INFO -- : Found config file /devver-repos/dacs/example/example.yml.
23
+ # >> W, [2010-02-14T09:45:52.704092 #17437] WARN -- : Unknown configuration key 'fuz' in file example.yml
23
24
  # >> Running in development mode
24
25
  # >> foo: file_foo
25
26
  # >> bar: env_bar
@@ -31,3 +32,15 @@ puts Dacs::AppConfig.dump # => nil
31
32
  # >> | foo | file_foo | file example.yml |
32
33
  # >> | bar | env_bar | environment |
33
34
  # >> +--------------------------------------+
35
+ # >> App name: example
36
+ # >> Environment: development
37
+ # >> Configuration file: /devver-repos/dacs/example/example.yml
38
+ # >> Configuration setup: -:5
39
+ # >> Env var prefix: EXAMPLE_
40
+ # >> +--------------------------------------+
41
+ # >> | Key | Value | Source |
42
+ # >> +--------------------------------------+
43
+ # >> | baz | default_baz | defaults |
44
+ # >> | foo | file_foo | file example.yml |
45
+ # >> | bar | env_bar | environment |
46
+ # >> +--------------------------------------+
@@ -41,7 +41,7 @@ module Dacs
41
41
 
42
42
  # Delegate a subset of Hash methods to the singleton instance
43
43
  def_delegators :instance, :[], :fetch, :key?, :merge, :merge!, :app_name,
44
- :source, :dump
44
+ :source, :dump, :report
45
45
 
46
46
  def_delegators :schema, :required?, :optional?, :keys, :default_value
47
47
  end
@@ -64,6 +64,7 @@ module Dacs
64
64
  @@options[:logger] ||= ::Logger.new($stderr)
65
65
  @@options[:environment] ||= :development
66
66
  @@options[:defaults] ||= {}
67
+ @@definition_location = caller[0]
67
68
  if block_given?
68
69
  schema = Schema.new
69
70
  yield(schema)
@@ -85,6 +86,10 @@ module Dacs
85
86
  def self.environment
86
87
  @@options[:environment]
87
88
  end
89
+
90
+ def self.definition_location
91
+ @@definition_location
92
+ end
88
93
 
89
94
  attr_reader :app_name
90
95
  attr_reader :logger
@@ -98,27 +103,37 @@ module Dacs
98
103
  @logger = @@options[:logger]
99
104
  @environment = @@options[:environment]
100
105
  @defaults = self.class.schema.defaults
106
+ @system = @@options.fetch(:system){Kernel}
101
107
  find_or_create_config_file!
102
108
 
103
109
  defaults_source = DefaultSource.new(@defaults)
104
110
  file_source = FileSource.new(config_path, @environment)
105
- env_source = EnvironmentSource.new(@app_name)
111
+ env_source = EnvironmentSource.new(env_var_prefix)
106
112
 
107
113
  load_values!(self.class.schema, env_source, file_source, defaults_source)
114
+ verify_no_missing_required_values!
115
+ end
116
+
117
+ def definition_location
118
+ self.class.definition_location
119
+ end
120
+
121
+ def env_var_prefix
122
+ app_name.to_s.upcase + "_"
108
123
  end
109
124
 
110
125
  def source(key)
111
- configured_value = Hash.instance_method(:fetch).bind(self).call(key.to_s) do
112
- raise ConfigurationError, "No such key '#{key}'"
113
- end
126
+ assert_key_defined!(key)
114
127
  configured_value.source.to_s
115
128
  end
116
129
 
117
130
  def [](key)
131
+ assert_key_defined!(key)
118
132
  super(key).value
119
133
  end
120
134
 
121
135
  def fetch(key, &block)
136
+ assert_key_defined!(key)
122
137
  case result = super(key, &block)
123
138
  when ConfiguredValue then result.value
124
139
  else result
@@ -133,8 +148,45 @@ module Dacs
133
148
  table.as(:text)
134
149
  end
135
150
 
151
+ def report
152
+ text = ""
153
+ text << "%-22s%s\n" % ["App name:", app_name]
154
+ text << "%-22s%s\n" % ["Environment:", environment]
155
+ text << "%-22s%s\n" % ["Configuration file:", config_path]
156
+ text << "%-22s%s\n" % ["Configuration setup:", definition_location]
157
+ text << "%-22s%s\n" % ["Env var prefix:", env_var_prefix]
158
+ text << dump
159
+ text
160
+ end
161
+
162
+ def verify_no_missing_required_values!
163
+ missing_keys = schema.keys - keys
164
+ missing_required_keys = missing_keys.select{|k| schema.required?(k)}
165
+ unless missing_required_keys.empty?
166
+ logger.fatal "Application not configured; exiting"
167
+ @system.warn "These required configuration keys were missing:"
168
+ missing_required_keys.each do |key|
169
+ @system.warn " #{key}"
170
+ end
171
+ @system.warn ""
172
+ @system.warn "Please set the required keys in #{config_path} or "\
173
+ "environment and try again."
174
+ @system.exit(1)
175
+ end
176
+ end
177
+
136
178
  private
137
179
 
180
+ def assert_key_defined!(key)
181
+ unless schema.defined?(key.to_s)
182
+ raise UndefinedKeyError, key, caller(3)
183
+ end
184
+ end
185
+
186
+ def schema
187
+ self.class.schema
188
+ end
189
+
138
190
  def find_or_create_config_file!
139
191
  if Pathname(config_path).exist?
140
192
  logger.info "Found config file #{config_path}."
@@ -174,8 +226,8 @@ END
174
226
  def load_values!(schema, *sources)
175
227
  sources.reverse_each do |source|
176
228
  source.each do |configured_value|
177
- if schema.defined?(configured_value.key)
178
- self[configured_value.key] = configured_value
229
+ if schema.defined?(configured_value.key.to_s)
230
+ self[configured_value.key.to_s] = configured_value
179
231
  else
180
232
  key = configured_value.key
181
233
  logger.warn "Unknown configuration key '#{key}' in #{source}"
@@ -1,7 +1,7 @@
1
1
  module Dacs
2
2
  class EnvironmentSource
3
- def initialize(app_name, environment=ENV)
4
- @app_name = app_name.to_s.downcase
3
+ def initialize(prefix, environment=ENV)
4
+ @prefix = prefix
5
5
  @environment = environment
6
6
  end
7
7
 
@@ -11,7 +11,7 @@ module Dacs
11
11
 
12
12
  def each
13
13
  @environment.each_pair do |key, value|
14
- if match = /^#{@app_name}_(.*)$/.match(key.downcase)
14
+ if match = /^#{@prefix.downcase}(.*)$/.match(key.downcase)
15
15
  yield ConfiguredValue.new(self, match[1], value)
16
16
  end
17
17
  end
data/lib/dacs/errors.rb CHANGED
@@ -1,3 +1,8 @@
1
1
  module Dacs
2
2
  ConfigurationError = Class.new(Exception)
3
+ class UndefinedKeyError < ConfigurationError
4
+ def initialize(key)
5
+ super("Unknown configuration key '#{key}'")
6
+ end
7
+ end
3
8
  end
data/lib/dacs/schema.rb CHANGED
@@ -31,7 +31,7 @@ module Dacs
31
31
 
32
32
  def defaults
33
33
  key_defs.inject({}) { |h, key_def|
34
- h[key_def[:name]] = key_def[:default]
34
+ h[key_def[:name]] = key_def[:default] if key_def.key?(:default)
35
35
  h
36
36
  }
37
37
  end
@@ -39,7 +39,7 @@ module Dacs
39
39
  private
40
40
 
41
41
  def assert_key_defined!(key)
42
- !!key_def(key) or raise ConfigurationError, "No configuration key '#{key}' is defined"
42
+ !!key_def(key) or raise UndefinedKeyError, key
43
43
  end
44
44
 
45
45
  def key_defs
@@ -59,6 +59,31 @@ module Dacs
59
59
  end
60
60
  end
61
61
 
62
+ context "given strict definitions and a missing required key" do
63
+ before :each do
64
+ @system = stub("system").as_null_object
65
+ end
66
+
67
+ def do_init
68
+ AppConfig.init!(@app_name, :logger => @logger, :system => @system) do |config|
69
+ config.key "foo"
70
+ config.key "bar"
71
+ end
72
+ end
73
+
74
+ it "should exit the program with an error status" do
75
+ @system.should_receive(:exit).with(1)
76
+ do_init
77
+ end
78
+
79
+ it "should warn the user about the missing config keys" do
80
+ @system.should_receive(:warn).with(/foo/)
81
+ @system.should_receive(:warn).with(/bar/)
82
+ @system.should_receive(:warn).any_number_of_times
83
+ do_init
84
+ end
85
+ end
86
+
62
87
  context "without explicit key definitions" do
63
88
  before :each do
64
89
  AppConfig.init!(@app_name,
@@ -91,12 +116,18 @@ module Dacs
91
116
 
92
117
  context "with explicit key definitions" do
93
118
  before :each do
119
+ ENV['FOO_APP_BAR'] = 'env_bar'
120
+ @def_line = __LINE__ + 1
94
121
  AppConfig.init!(@app_name, :logger => @logger) do |config|
95
122
  config.key :foo, :default => 42
96
123
  config.key 'bar'
97
124
  end
98
125
  end
99
126
 
127
+ after :each do
128
+ ENV.delete('FOO_APP_BAR')
129
+ end
130
+
100
131
  it "should be able to list known keys" do
101
132
  AppConfig.keys.should == ['foo', 'bar']
102
133
  end
@@ -115,6 +146,25 @@ module Dacs
115
146
  AppConfig.optional?(:foo).should be_true
116
147
  end
117
148
 
149
+ it "should raise an exception when an undefined key is referenced" do
150
+ lambda do
151
+ AppConfig['faz']
152
+ end.should raise_error(ConfigurationError)
153
+ end
154
+
155
+ it "should reference the offending line when an undefined key is referenced" do
156
+ @error_line = __LINE__ + 2
157
+ error = begin
158
+ AppConfig['faz']
159
+ rescue ConfigurationError => error
160
+ error
161
+ end
162
+ error.backtrace[0].should match(/#{__FILE__}:#{@error_line}/)
163
+ end
164
+
165
+ it "should remember where the keys were defined" do
166
+ AppConfig.definition_location.should match(/#{__FILE__}:#{@def_line}/)
167
+ end
118
168
  end
119
169
 
120
170
  context "with a mix of default, file, and environment settings" do
@@ -136,6 +186,10 @@ module Dacs
136
186
  end
137
187
  end
138
188
 
189
+ after :each do
190
+ ENV.delete('FOO_APP_BUZ')
191
+ end
192
+
139
193
  it "should have the correct values for each" do
140
194
  AppConfig['foo'].should be == 42
141
195
  AppConfig['bar'].should be == 'file_bar'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dacs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Devver, Inc.
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-02-13 00:00:00 -05:00
12
+ date: 2010-02-14 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency