mixlib-config 2.0.0.rc.2 → 2.0.0.rc.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,41 +1,129 @@
1
- ## Mixlib::Config
1
+ # Mixlib::Config #
2
2
 
3
3
  Mixlib::Config provides a class-based configuration object, as used in Chef. To use in your project:
4
4
 
5
- require 'rubygems'
5
+ ```ruby
6
6
  require 'mixlib/config'
7
7
 
8
- class MyConfig
9
- extend(Mixlib::Config)
10
- configure do |c|
11
- c[:first_value] = 'something'
12
- c[:other_value] = 'something_else'
13
- end
8
+ module MyConfig
9
+ extend Mixlib::Config
10
+ config_strict_mode true
11
+ default :first_value, 'something'
12
+ default :other_value, 'something_else'
14
13
  end
14
+ ```
15
15
 
16
- Or...
16
+ You can use this to provide a configuration file for a user. For example, if you do this:
17
17
 
18
- class MyConfig
19
- extend(Mixlib::Config)
18
+ ```ruby
19
+ MyConfig.from_file('~/.myconfig.rb')
20
+ ```
20
21
 
21
- first_value 'something'
22
- other_value 'something_else'
23
- end
22
+ A user could write a Ruby config file that looked like this:
23
+
24
+ ```ruby
25
+ first_value 'hi'
26
+ second_value "#{first_value}! 10 times 10 is #{10*10}!"
27
+ ```
24
28
 
25
- To check a configuration variable:
29
+ Inside your app, you can check configuration values with this syntax:
26
30
 
31
+ ```ruby
27
32
  MyConfig.first_value # returns 'something'
28
33
  MyConfig[:first_value] # returns 'something'
34
+ ```
35
+ And you can modify configuration values with this syntax:
29
36
 
30
- To change a configuration variable at runtime:
31
-
37
+ ```ruby
32
38
  MyConfig.first_value('foobar') # sets first_value to 'foobar'
39
+ MyConfig.first_value = 'foobar' # sets first_value to 'foobar'
33
40
  MyConfig[:first_value] = 'foobar' # sets first_value to 'foobar'
41
+ ```
42
+
43
+ ## Nested Configuration ##
44
+
45
+ Often you want to be able to group configuration options to provide a common context. Mixlib::Config supports this thus:
46
+
47
+ ```ruby
48
+ require 'mixlib/config'
49
+
50
+ module MyConfig
51
+ extend Mixlib::Config
52
+ config_context :logging do
53
+ default :base_filename, 'mylog'
54
+ default :max_log_files, 10
55
+ end
56
+ end
57
+ ```
58
+
59
+ The user can write their config file like this:
60
+
61
+ ```ruby
62
+ logging.base_filename 'superlog'
63
+ logging.max_log_files 2
64
+ ```
65
+
66
+ You can access these variables thus:
67
+
68
+ ```ruby
69
+ MyConfig.logging.base_filename
70
+ MyConfig[:logging][:max_log_files]
71
+ ```
72
+
73
+ ## Default Values ##
74
+
75
+ Mixlib::Config has a powerful default value facility. In addition to being able to specify explicit default values, you can even specify Ruby code blocks that will run if the config value is not set. This can allow you to build options whose values are based on other options.
76
+
77
+ ```ruby
78
+ require 'mixlib/config'
79
+
80
+ module MyConfig
81
+ extend Mixlib::Config
82
+ config_strict_mode true
83
+ default :verbosity, 1
84
+ default(:print_network_requests) { verbosity >= 2 }
85
+ default(:print_ridiculously_unimportant_stuff) { verbosity >= 10 }
86
+ end
87
+ ```
88
+
89
+ This allows the user to quickly specify a number of values with one default, while still allowing them to override anything:
90
+
91
+ ```ruby
92
+ verbosity 5
93
+ print_network_requests false
94
+ ```
95
+
96
+ ## Strict Mode ##
97
+
98
+ Misspellings are a common configuration problem, and Mixlib::Config has an answer: `config_strict_mode`. Setting `config_strict_mode` to `true` will cause any misspelled or incorrect configuration option references to throw `Mixlib::Config::UnknownConfigOptionError`.
99
+
100
+ ```ruby
101
+ require 'mixlib/config'
102
+
103
+ module MyConfig
104
+ extend Mixlib::Config
105
+ config_strict_mode true
106
+ default :filename, '~/output.txt'
107
+ configurable :server_url # configurable declares an option with no default value
108
+ config_context :logging do
109
+ default :base_name, 'log'
110
+ default :max_files, 20
111
+ end
112
+ end
113
+ ```
114
+
115
+ Now if a user types `fielname "~/output-mine.txt"` in their configuration file, it will toss an exception telling them that the option "fielname" is unknown. If you do not set config_strict_mode, the fielname option will be merrily set and the application just won't know about it.
116
+
117
+ Different config_contexts can have different strict modes; but they inherit the strict mode of their parent if you don't explicitly set it. So setting it once at the top level is sufficient. In the above example, `logging.base_naem 'mylog'` will raise an error.
118
+
119
+ In conclusion: *always set config_strict_mode to true*. You know you want to.
120
+
121
+ ## Testing and Reset ##
34
122
 
35
- You should populate your class with the default values for every configuration variable that might be accessed. If you try and access a variable that does not exist, Mixlib::Config will throw an <ArgumentError>.
123
+ Testing your application with different sets of arguments can by simplified with `reset`. Call `MyConfig.reset` before each test and all configuration will be reset to its default value. There's no need to explicitly unset all your options between each run.
36
124
 
37
- To load a ruby configuration file (which will evaluate in the context of your configuration class):
125
+ NOTE: if you have arrays of arrays, or other deep nesting, we suggest you use code blocks to set up your default values (`default(:option) { [ [ 1, 2 ], [ 3, 4 ] ] }`). Deep children will not always be reset to their default values.
38
126
 
39
- MyConfig.from_file('your_config_file.rb')
127
+ Report bugs [here](https://tickets.opscode.com).
40
128
 
41
129
  Enjoy!
data/lib/mixlib/config.rb CHANGED
@@ -28,10 +28,10 @@ module Mixlib
28
28
  class << base; attr_accessor :configuration; end
29
29
  class << base; attr_accessor :configurables; end
30
30
  class << base; attr_accessor :config_contexts; end
31
+ class << base; attr_accessor :config_parent; end
31
32
  base.configuration = Hash.new
32
33
  base.configurables = Hash.new
33
34
  base.config_contexts = Array.new
34
- base.config_strict_mode false
35
35
  end
36
36
 
37
37
  # Loads a given ruby file, and runs instance_eval against it in the context of the current
@@ -208,6 +208,7 @@ module Mixlib
208
208
  def config_context(symbol, &block)
209
209
  context = Class.new
210
210
  context.extend(::Mixlib::Config)
211
+ context.config_parent = self
211
212
  config_contexts << context
212
213
  if block
213
214
  context.instance_eval(&block)
@@ -238,7 +239,15 @@ module Mixlib
238
239
  #
239
240
  def config_strict_mode(value = NOT_PASSED)
240
241
  if value == NOT_PASSED
241
- @config_strict_mode
242
+ if @config_strict_mode.nil?
243
+ if config_parent
244
+ config_parent.config_strict_mode
245
+ else
246
+ false
247
+ end
248
+ else
249
+ @config_strict_mode
250
+ end
242
251
  else
243
252
  self.config_strict_mode = value
244
253
  end
@@ -258,8 +267,8 @@ module Mixlib
258
267
  # <ArgumentError>:: if value is set to something other than true, false, or :warn
259
268
  #
260
269
  def config_strict_mode=(value)
261
- if ![ true, false, :warn ].include?(value)
262
- raise ArgumentError, "config_strict_mode must be true, false or :warn"
270
+ if ![ true, false, :warn, nil ].include?(value)
271
+ raise ArgumentError, "config_strict_mode must be true, false, nil or :warn"
263
272
  end
264
273
  @config_strict_mode = value
265
274
  end
@@ -43,7 +43,12 @@ module Mixlib
43
43
  elsif @default
44
44
  @default.call
45
45
  else
46
- @default_value
46
+ begin
47
+ # Some things cannot be dup'd, and you won't know this till after the fact
48
+ config[@symbol] = @default_value.dup
49
+ rescue TypeError
50
+ @default_value
51
+ end
47
52
  end
48
53
  end
49
54
 
@@ -19,7 +19,7 @@
19
19
  module Mixlib
20
20
  module Config
21
21
 
22
- VERSION = "2.0.0.rc.2"
22
+ VERSION = "2.0.0.rc.3"
23
23
 
24
24
  end
25
25
  end
@@ -177,7 +177,7 @@ describe Mixlib::Config do
177
177
 
178
178
  end
179
179
 
180
- describe "When a default value exists" do
180
+ describe "When config has a default value" do
181
181
  before :each do
182
182
  @klass = Class.new
183
183
  @klass.extend(::Mixlib::Config)
@@ -210,7 +210,52 @@ describe Mixlib::Config do
210
210
  end
211
211
  end
212
212
 
213
- describe "When a default value block exists" do
213
+ describe "When config has an array default value" do
214
+ before :each do
215
+ @klass = Class.new
216
+ @klass.extend(::Mixlib::Config)
217
+ @klass.class_eval { default :attr, [] }
218
+ end
219
+
220
+ it "reset clears it to its default" do
221
+ @klass.attr << 'x'
222
+ @klass.attr.should == [ 'x' ]
223
+ @klass.reset
224
+ @klass.attr.should == []
225
+ end
226
+ end
227
+
228
+ describe "When config has a hash default value" do
229
+ before :each do
230
+ @klass = Class.new
231
+ @klass.extend(::Mixlib::Config)
232
+ @klass.class_eval { default :attr, {} }
233
+ end
234
+
235
+ it "reset clears it to its default" do
236
+ @klass.attr[:x] = 10
237
+ @klass.attr[:x].should == 10
238
+ @klass.reset
239
+ @klass.attr[:x].should == nil
240
+ end
241
+ end
242
+
243
+ describe "When config has a string default value" do
244
+ before :each do
245
+ @klass = Class.new
246
+ @klass.extend(::Mixlib::Config)
247
+ @klass.class_eval { default :attr, 'hello' }
248
+ end
249
+
250
+ it "reset clears it to its default" do
251
+ @klass.attr << ' world'
252
+ @klass.attr.should == 'hello world'
253
+ @klass.reset
254
+ @klass.attr.should == 'hello'
255
+ end
256
+ end
257
+
258
+ describe "When config has a a default value block" do
214
259
  before :each do
215
260
  @klass = Class.new
216
261
  @klass.extend(::Mixlib::Config)
@@ -447,8 +492,8 @@ describe Mixlib::Config do
447
492
  lambda { StrictClass3.y = 10 }.should raise_error(Mixlib::Config::UnknownConfigOptionError)
448
493
  end
449
494
 
450
- it "The nested class allows you to set arbitrary config options" do
451
- StrictClass3.c.y = 10
495
+ it "The nested class does not allow you to set arbitrary config options" do
496
+ lambda { StrictClass3.y = 10 }.should raise_error(Mixlib::Config::UnknownConfigOptionError)
452
497
  end
453
498
  end
454
499
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mixlib-config
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.rc.2
4
+ version: 2.0.0.rc.3
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-09-11 00:00:00.000000000 Z
12
+ date: 2013-09-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake