confection 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.ruby CHANGED
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  source:
3
- - profile
3
+ - var
4
4
  authors:
5
5
  - name: Trans
6
6
  email: transfire@gmail.com
@@ -8,10 +8,14 @@ copyrights:
8
8
  - holder: Rubyworks
9
9
  year: '2011'
10
10
  license: BSD-2-Clause
11
- replacements: []
12
- alternatives: []
13
11
  requirements:
12
+ - name: finder
13
+ - name: facets
14
14
  - name: blankslate
15
+ groups:
16
+ - optional
17
+ - test
18
+ development: true
15
19
  - name: detroit
16
20
  groups:
17
21
  - build
@@ -20,7 +24,12 @@ requirements:
20
24
  groups:
21
25
  - test
22
26
  development: true
27
+ - name: ae
28
+ groups:
29
+ - test
30
+ development: true
23
31
  dependencies: []
32
+ alternatives: []
24
33
  conflicts: []
25
34
  repositories:
26
35
  - uri: git://github.com/rubyworks/confection.git
@@ -38,8 +47,8 @@ revision: 0
38
47
  created: '2011-11-06'
39
48
  summary: Multi-tenant configuration for Ruby
40
49
  title: Confection
41
- version: 0.1.0
50
+ version: 0.2.0
42
51
  name: confection
43
52
  description: Confection is a multi-tenant configuration system for Ruby projects.
44
53
  organization: Rubyworks
45
- date: '2011-11-17'
54
+ date: '2012-03-11'
@@ -1,6 +1,21 @@
1
- = RELEASE HISTORY
1
+ # RELEASE HISTORY
2
2
 
3
- == 0.1.0 | 2011-11-17
3
+ ## 0.2.0 | 2012-03-11
4
+
5
+ The API has changed and no longer uses #method_missing magic.
6
+ Instead the `config` method is used to define a configuration.
7
+ In addition Confection now supports profiles via either a
8
+ block clause or via a second argument, as well as the ability
9
+ to import configurations from other projects.
10
+
11
+ Changes:
12
+
13
+ * Use #config method instead of method_missing trick.
14
+ * Add support for configuration profiles.
15
+ * Add #confect method to automatically handle typical configuration.
16
+
17
+
18
+ ## 0.1.0 | 2011-11-17
4
19
 
5
20
  This major release, probably the first truly usable release,
6
21
  adds support for multiple configration files by storing them
@@ -17,7 +32,7 @@ Changes:
17
32
  support multiple configurations at once.
18
33
 
19
34
 
20
- == 0.0.2 | 2011-11-07
35
+ ## 0.0.2 | 2011-11-07
21
36
 
22
37
  You can now use $CONFIG_FILE to change the default config file.
23
38
  Just set the variable prior to using confection. Confection
@@ -30,7 +45,7 @@ Changes:
30
45
  * Add $CONFIG_FILE to allow default config file to be adjusted.
31
46
 
32
47
 
33
- == 0.0.1 | 2011-11-06
48
+ ## 0.0.1 | 2011-11-06
34
49
 
35
50
  This is the initial release of Confection.
36
51
 
data/LICENSE.txt ADDED
@@ -0,0 +1,27 @@
1
+ Confection (http://rubyworks.github.com/confection)
2
+
3
+ Copyright (c) 2011 Rubyworks. All rights reserved.
4
+
5
+ License (spdx) BSD-2-Clause
6
+
7
+ Redistribution and use in source and binary forms, with or without
8
+ modification, are permitted provided that the following conditions are met:
9
+
10
+ 1. Redistributions of source code must retain the above copyright notice,
11
+ this list of conditions and the following disclaimer.
12
+
13
+ 2. Redistributions in binary form must reproduce the above copyright
14
+ notice, this list of conditions and the following disclaimer in the
15
+ documentation and/or other materials provided with the distribution.
16
+
17
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
19
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+
data/README.md ADDED
@@ -0,0 +1,149 @@
1
+ # Confection
2
+
3
+ [Homepage](http://rubyworks.github.com/confection) |
4
+ [Source Code](http://github.com/rubyworks/confection) |
5
+ [Report Issue](http://github.com/rubyworks/confection/issues) |
6
+ [Mailing List](http://googlegroups.com/group/rubyworks-mailinglist) |
7
+ [IRC Channel](http://chat.us.freenode.net/rubyworks)
8
+
9
+ [![Build Status](https://secure.travis-ci.org/rubyworks/confection.png)](http://travis-ci.org/rubyworks/confection)
10
+
11
+
12
+ ## Description
13
+
14
+ Confection is multi-tenant configuration system for Ruby projects. If was
15
+ designed to facilitate Ruby-based configuration for multiple tools in a
16
+ single file. It is extremely simple, which makes it easy to understand
17
+ and flexible in use.
18
+
19
+
20
+ ## Instruction
21
+
22
+ To get started, create a file in you project called `Confile`. The file can
23
+ have any name that matches the glob `{.,}confile{.rb,}` case insensitive. In
24
+ this file add configuration blocks by name. For example, let's demonstrate
25
+ how we could use this to configure Rake tasks.
26
+
27
+ $ cat Confile
28
+ config :rake do
29
+ desc 'generate yard docs'
30
+ task :yard do
31
+ sh 'yard'
32
+ end
33
+ end
34
+
35
+ In our Rakefile:
36
+
37
+ $ cat Rakefile
38
+ require 'confection'
39
+ confection(:rake, '*').load
40
+
41
+ Now you might wonder why the heck you would do this. That's where the *multi-tenancy*
42
+ comes into play. Let's add another configuration, and this time for a tool that has
43
+ native support for Confection.
44
+
45
+ $ cat Confile
46
+ title = "MyApp"
47
+
48
+ config :rake do
49
+ desc 'generate yard docs'
50
+ task :yard do
51
+ sh "yard doc --title #{title}"
52
+ end
53
+ end
54
+
55
+ config :qedoc do |doc|
56
+ doc.title = "#{title} Demonstrandum"
57
+ end
58
+
59
+ Now we have configuration for both the rake tool and the qedoc tool in
60
+ a single file. Thus we gain the advantage of reducing the file count of our
61
+ project while pulling our tool configurations together into one place.
62
+ Moreover, these configurations can potentially share settings as demonstrated
63
+ here via the `title` variable.
64
+
65
+ Confection also supports profiles, either via a `profile` block or via a
66
+ second config argument.
67
+
68
+ config :qed, :cov do
69
+ require 'simplecov'
70
+ ...
71
+ end
72
+
73
+ Or,
74
+
75
+ profile :cov
76
+ config :qed do
77
+ require 'simplecov'
78
+ ...
79
+ end
80
+ end
81
+
82
+ Using Confection in your libraries is very simple, as can be seen from our
83
+ Rakefile example. The `#confection` method (alias `#config`) is used to get
84
+ a handle on a named configuration. With it you have a few options, `#call`,
85
+ `#exec` or `#load`, `#to_s` or `#to_h`.
86
+
87
+ The `#call` method evaluates a config's block in a separate per-configuration
88
+ file context in which it was defined. This is recommended. The `#exec` method,
89
+ on the other hand, will evaluate the block in the context of the caller. Where
90
+ as the `#load` method evaluates the block in the toplevel context.
91
+
92
+ For instance, QED uses `#exec` to import user configuration directly into
93
+ its Settings instance.
94
+
95
+ confection(:qed, profile_name).exec
96
+
97
+ The last two methods, `#to_s` and `#to_h` are used for text-based or hash-based
98
+ configurations. The `qedoc` configuration above is a good example of the later.
99
+ It can be converted directly into a Hash.
100
+
101
+ confection(:qedoc, :cov).to_h #=> {:title => "MyApp Demonstration"}
102
+
103
+ Lastly, there is the `#confect` method (alias `#configure`). This is just like the
104
+ `#confection` method, but automatically invokes `configure(self)` on each
105
+ selected configuration. In most cases that's exactly what is needed, so it
106
+ saves having to make the additional invocation on the return value of `#confection`.
107
+
108
+
109
+ ## Dependencies
110
+
111
+ ### Libraries
112
+
113
+ Confection depends on the [Finder](http://rubyworks.github.com/finder) library
114
+ to provide reliable load path and Gem searching. This is used when importing
115
+ configurations from external projects.
116
+
117
+ Confection also depends on [Ruby Facets](http://rubyworks.github.com/facets)
118
+ for just a few very useful core extensions.
119
+
120
+ To use Confection on Ruby 1.8 series, the `BlankSlate` library is also needed
121
+ in order to emulate Ruby's BasicObject. (This may change to the `Backports`
122
+ project in a future version.)
123
+
124
+ ### Core Extensions
125
+
126
+ Confection uses two core extensions, `#to_h`, which applies a few different
127
+ classes, `String#tabto`. These come from Ruby Facets to ensure a high standard
128
+ of interoperability.
129
+
130
+ Both of these methods have been suggested for inclusion in Ruby proper.
131
+ Please head over to Ruby Issue Tracker and add your support.
132
+
133
+ * http://bugs.ruby-lang.org/issues/749
134
+ * http://bugs.ruby-lang.org/issues/6056
135
+
136
+
137
+ ## Release Notes
138
+
139
+ Please see HISTORY.rdoc file.
140
+
141
+
142
+ ## Copyrights
143
+
144
+ Copyright (c) 2011 Rubyworks
145
+
146
+ Confection is distributable in accordance with the **BSD-2-Clause** license.
147
+
148
+ See LICENSE.txt file for details.
149
+
@@ -1,3 +1,5 @@
1
+ # TODO: Maybe use `backports` for future version.
2
+
1
3
  unless Object.const_defined?(:BasicObject)
2
4
  require 'blankslate'
3
5
  Object::BasicObject = Object::BlankSlate
@@ -0,0 +1,170 @@
1
+ module Confection
2
+
3
+ # Config encapsulates a single configuration entry as defined
4
+ # in a project's configuration file.
5
+ #
6
+ class Config
7
+
8
+ #
9
+ # Initialize Config instance. Config instances are per-configuration,
10
+ # which means they are associated with one and only one config entry.
11
+ #
12
+ def initialize(tool, profile, context, value, &block)
13
+ self.tool = tool
14
+ self.profile = profile
15
+ self.value = value
16
+ self.block = block if block
17
+
18
+ @context = context
19
+ end
20
+
21
+ #
22
+ # The name of tool being configured.
23
+ #
24
+ attr :tool
25
+
26
+ #
27
+ # Change the tool name. Note, this will rarely be used since,
28
+ # generally speaking, configurations tend to be very tool
29
+ # specific.
30
+ #
31
+ def tool=(name)
32
+ @tool = name.to_sym
33
+ end
34
+
35
+ #
36
+ # The name of the profile to which this configuration belongs.
37
+ #
38
+ attr :profile
39
+
40
+ #
41
+ # Change the profile name.
42
+ #
43
+ def profile=(name)
44
+ @profile = name.to_sym if name
45
+ end
46
+
47
+ #
48
+ # Some configuration are simple values. In those cases
49
+ # the `@value` attributes holds the object, otherwise it
50
+ # is `nil`.
51
+ #
52
+ def value
53
+ @value
54
+ end
55
+
56
+ #
57
+ # Set the configuration value.
58
+ #
59
+ # @param [Object] value
60
+ # The configuration value.
61
+ #
62
+ def value=(value)
63
+ @block = nil
64
+ @value = value
65
+ end
66
+
67
+ #
68
+ # Most configuration are scripted. In thos cases the
69
+ # `@block` attributes holds the Proc instance, otherwise
70
+ # it is `nil`.
71
+ #
72
+ attr :block
73
+
74
+ #
75
+ # Set the configuration procedure.
76
+ #
77
+ # @param [Proc] procedure
78
+ # The configuration procedure.
79
+ #
80
+ def block=(proc)
81
+ @value = nil
82
+ @block = proc.to_proc
83
+ end
84
+
85
+ #
86
+ # The arity of the configuration procedure.
87
+ #
88
+ # @return [Fixnum] number of arguments
89
+ #
90
+ def arity
91
+ @block ? @block.arity : 0
92
+ end
93
+
94
+ #
95
+ # Call the procedure. Configuration procedures are evaluated
96
+ # in the scope of a per-configuration file context instance,
97
+ # which is extended by the {DSL} evaluation context.
98
+ #
99
+ def call(*args)
100
+ #@value || @block.call(*args)
101
+ @value || @context.instance_exec(*args, &block)
102
+ end
103
+
104
+ #
105
+ # Convert the underlying procedure into an `instance_exec`
106
+ # procedure. This allows the procedure to be evaluated in
107
+ # any scope that it is be needed.
108
+ #
109
+ def to_proc
110
+ if value = @value
111
+ lambda{ value }
112
+ else
113
+ block = @block
114
+ lambda do |*args|
115
+ instance_exec(*args, &block)
116
+ end
117
+ end
118
+ end
119
+
120
+ #
121
+ # Return the value or procedure in the form of a Hash.
122
+ #
123
+ # @return [Hash]
124
+ #
125
+ def to_h
126
+ (@value || HashBuilder.new(&@block)).to_h
127
+ end
128
+
129
+ #
130
+ # Return the value or procedure in the form of a String.
131
+ #
132
+ # @return [String]
133
+ #
134
+ def to_s
135
+ (@value || call).to_s
136
+ end
137
+
138
+ #
139
+ # Alias for #to_s.
140
+ #
141
+ # @todo Should this alias be deprecated?
142
+ #
143
+ alias text to_s
144
+
145
+ #
146
+ # Copy the configuration with alterations.
147
+ #
148
+ # @param [Hash] alt
149
+ # Alternate values for configuration attributes.
150
+ #
151
+ # @return [Config] copied config
152
+ #
153
+ def copy(alt={})
154
+ copy = dup
155
+ alt.each do |k,v|
156
+ copy.__send__("#{k}=", v)
157
+ end
158
+ copy
159
+ end
160
+
161
+ #
162
+ # Ruby 1.9 defines #inspect as #to_s, ugh.
163
+ #
164
+ def inspect
165
+ "#<#{self.class.name}:#{object_id} @tool=%s @profile=%s>" % [tool.inspect, profile.inspect]
166
+ end
167
+
168
+ end
169
+
170
+ end
@@ -0,0 +1,175 @@
1
+ module Confection
2
+
3
+ # The Controller class is used to encapsulate the various methods of invocation
4
+ # that are posible on configuration blocks. It applies those invocations
5
+ # across it's set of configurations.
6
+ #
7
+ class Controller
8
+
9
+ include Enumerable
10
+
11
+ #
12
+ # Initialize new Controller instance.
13
+ #
14
+ # @param [Object] scope
15
+ #
16
+ # @param [Array<Config>] configs
17
+ #
18
+ def initialize(scope, *configs)
19
+ @scope = scope
20
+ @configs = configs
21
+ end
22
+
23
+ #
24
+ # Iterate over each config.
25
+ #
26
+ def each(&block)
27
+ @configs.each(&block)
28
+ end
29
+
30
+ #
31
+ # Number of configs.
32
+ #
33
+ def size
34
+ @configs.size
35
+ end
36
+
37
+ #
38
+ # Execute the configuration code.
39
+ #
40
+ def call(*args)
41
+ result = nil
42
+ each do |config|
43
+ result = config.call(*args)
44
+ end
45
+ result
46
+ end
47
+
48
+ #
49
+ # Special configuration call.
50
+ #
51
+ def configure
52
+ result = nil
53
+ each do |config|
54
+ case config.arity
55
+ when 0
56
+ exec
57
+ when 1
58
+ result = config.call(@scope)
59
+ end
60
+ end
61
+ result
62
+ end
63
+
64
+ #
65
+ # Evaluate configuration in the context of the caller.
66
+ #
67
+ # This is the same as calling:
68
+ #
69
+ # instance_exec(*args, &config)
70
+ #
71
+ def exec(*args)
72
+ result = nil
73
+ each do |config|
74
+ if config.respond_to?(:to_proc)
75
+ #@scope.extend(config.dsl) # ?
76
+ result = @scope.instance_exec(*args, &config)
77
+ end
78
+ end
79
+ result
80
+ end
81
+
82
+ #
83
+ # Load config as script code in context of TOPLEVEL.
84
+ #
85
+ # This is the same as calling:
86
+ #
87
+ # main = ::TOPLEVEL_BINDING.eval('self')
88
+ # main.instance_exec(*args, &config)
89
+ #
90
+ def main_exec(*args)
91
+ result = nil
92
+ main = ::Kernel.eval('self', ::TOPLEVEL_BINDING) # ::TOPLEVEL_BINDING.eval('self') [1.9+]
93
+ each do |config|
94
+ if config.respond_to?(:to_proc)
95
+ #main.extend(config.dsl)
96
+ result = main.instance_exec(*args, &config)
97
+ end
98
+ end
99
+ result
100
+ end
101
+
102
+ # @deprecated Alias for `#main_exec` might be deprecated in future.
103
+ alias load main_exec
104
+
105
+ #
106
+ # Only applicable to script and block configs, this method converts
107
+ # a set of code configs into a single block ready for execution.
108
+ #
109
+ def to_proc
110
+ #properties = ::Confection.properties # do these even matter here ?
111
+ __configs__ = @configs
112
+ block = Proc.new do |*args|
113
+ result = nil
114
+ #extend dsl # TODO: extend DSL into instance context ?
115
+ __configs__.each do |config|
116
+ if config.respond_to?(:to_proc)
117
+ result = instance_exec(*args, &config)
118
+ end
119
+ end
120
+ result
121
+ end
122
+ end
123
+
124
+ #
125
+ # Configurations texts joins together the contents of each
126
+ # configuration separated by two newlines (`\n\n`).
127
+ #
128
+ def to_s
129
+ txt = []
130
+ @configs.each do |c|
131
+ txt << c.to_s #if c.text
132
+ end
133
+ txt.join("\n\n")
134
+ end
135
+
136
+ alias text to_s
137
+
138
+ #
139
+ #
140
+ #
141
+ def to_h
142
+ hsh = {}
143
+ @configs.each do |c|
144
+ hsh.merge!(c.to_h)
145
+ end
146
+ hsh
147
+ end
148
+
149
+ ##
150
+ ## Treat configurations as YAML mappings, load, merge and return.
151
+ ##
152
+ #def yaml
153
+ # @configs.inject({}) do |h, c|
154
+ # h.merge(c.yaml)
155
+ # end
156
+ #end
157
+
158
+ #
159
+ # Inspection string for controller.
160
+ #
161
+ def inspect
162
+ "#<#{self.class}##{object_id}>"
163
+ end
164
+
165
+ end
166
+
167
+ #
168
+ #class NullController
169
+ # def exec(*); end
170
+ # def call(*); end
171
+ # def text; ''; end
172
+ # alias to_s text
173
+ #end
174
+
175
+ end
@@ -0,0 +1,154 @@
1
+ module Confection
2
+
3
+ # The File class is used to evaluate the configuration file.
4
+ #
5
+ class DSL < Module #BasicObject
6
+
7
+ #
8
+ # Create new DSL instance and parse file.
9
+ #
10
+ # @todo Does the exception rescue make sense here?
11
+ #
12
+ def self.parse(store, file)
13
+ dsl = new(store, file)
14
+ begin
15
+ text = File.read(file)
16
+ rescue => e
17
+ raise e if $DEBUG
18
+ warn e.message
19
+ end
20
+ dsl.instance_eval(text, file)
21
+ end
22
+
23
+ #
24
+ # Initialize new DSL object.
25
+ #
26
+ # @param [Store] store
27
+ # The configuration storage instance.
28
+ #
29
+ # @param [String] file
30
+ # Configuration file to load.
31
+ #
32
+ def initialize(store, file=nil)
33
+ @_store = store
34
+ @_file = file
35
+
36
+ @_contest = Object.new
37
+ @_context.extend self
38
+
39
+ @_options = {}
40
+ end
41
+
42
+ # TODO: Separate properties from project metadata ?
43
+
44
+ #
45
+ # Profile block.
46
+ #
47
+ def profile(name, options={}, &block)
48
+ raise SyntaxError, "nested tool sections" if @_options[:profile]
49
+
50
+ original_state = @_options.dup
51
+
52
+ @_options.update(options) # TODO: maybe be more exacting about this
53
+ @_options[:profile] = name.to_sym
54
+
55
+ instance_eval(&block)
56
+
57
+ @_options = original_state
58
+ end
59
+
60
+ #
61
+ # Configure a tool.
62
+ #
63
+ # @param [Symbol] tool
64
+ # The name of the tool to configure.
65
+ #
66
+ # @param [Hash] opts
67
+ # Configuration options.
68
+ #
69
+ # @options opts [String] :file
70
+ # File from which to load configuration.
71
+ #
72
+ # @options opts [String] :text
73
+ # Text of text-based configuration.
74
+ #
75
+ # @example
76
+ # config :rake, "*.rake"
77
+ #
78
+ # @example
79
+ # profile :cov do
80
+ # config :qed, "qed/simplecov.rb"
81
+ # end
82
+ #
83
+ # @todo Clean this code up.
84
+ #
85
+ def config(tool, *args, &block)
86
+ case args.first
87
+ when Symbol
88
+ profile = args.shift
89
+ when String
90
+ profile = args.shift unless args.first.index("\n")
91
+ end
92
+
93
+ case args.first
94
+ when Hash
95
+ data = args.shift
96
+ from = data[:from] # special key
97
+ when Proc
98
+ data = args.shift
99
+ # TODO convert data into OpenHash like object
100
+ when String
101
+ data = args.shift
102
+ data = data.tabto(0)
103
+ end
104
+
105
+ raise ArgumentError, "too many arguments" if args.first
106
+ raise SyntaxError, "nested profile sections" if profile && @_options[:profile]
107
+ #raise ArgumentError, "use block or :from setting" if options[:from] && block
108
+
109
+ profile = @_options[:profile] unless profile
110
+
111
+ if from
112
+ @_store.import(tool, profile, data, &block)
113
+ data = nil
114
+ return unless block
115
+ end
116
+
117
+ #original_state = @_options.dup
118
+
119
+ if data && block
120
+ raise ArgumentError, "must use data or block, not both"
121
+ end
122
+
123
+ @_store << Config.new(tool, profile, @_context, data, &block)
124
+
125
+ #@_options = original_state
126
+ end
127
+
128
+ # TODO: use `:default` profile instead of `nil` ?
129
+
130
+ #
131
+ # Evaluate script directory into current scope.
132
+ #
133
+ # @todo Make a core extension ?
134
+ #
135
+ def import(feature)
136
+ file = Find.load_path(feature).first
137
+ raise LoadError, "no such file -- #{feature}" unless file
138
+ instance_eval(::File.read(file), file) if file
139
+ end
140
+
141
+ ##
142
+ ## Cached binding.
143
+ ##
144
+ #def __binding__
145
+ # @_binding ||= binding
146
+ #end
147
+
148
+ #def __eval__(code, file=nil)
149
+ # Kernel.eval(code, __binding__, file || '(eval)')
150
+ #end
151
+
152
+ end
153
+
154
+ end
data/lib/confection.rb CHANGED
@@ -1,162 +1,50 @@
1
- require 'confection/basic_object'
2
-
3
1
  # Welcome to Confection. Your easy means to tool configuration.
4
2
  #
5
3
  module Confection
4
+ end
6
5
 
7
- #
8
- @config = Hash.new{|h,k| h[k]={}}
9
-
10
- #
11
- def self.filename
12
- @filename ||= (
13
- $CONFIG_FILE ? $CONFIG_FILE : '{.,}confile{.rb,}'
14
- )
15
- end
16
-
17
- # Configuration file can be changed using this method.
18
- # Alternatively it can be changed using `$CONFIG_FILE`.
19
- def self.filename=(glob)
20
- @filename = glob
21
- end
22
-
23
- # Bootstrap the system, loading current configurations.
24
- #
25
- def self.bootstrap
26
- if file
27
- @config[Dir.pwd] = {}
28
- begin
29
- ::Kernel.eval(read, Evaluator.binding, file)
30
- rescue => e
31
- raise e if $DEBUG
32
- warn e.message
33
- end
34
- end
35
- @config[Dir.pwd]
36
- end
37
-
38
- # Stores the configuration blocks.
39
- #
40
- # @return [Hash] configuration store
41
- def self.config
42
- if @config.key?(Dir.pwd)
43
- @config[Dir.pwd]
44
- else
45
- bootstrap
46
- end
47
- end
48
-
49
- # Look-up configuration block.
50
- #
51
- # @param name [Symbol,String]
52
- # The identifying name for the config block.
53
- #
54
- def self.[](name)
55
- config[name.to_sym]
56
- end
57
-
58
- # Set configuration block.
59
- #
60
- # @param name [Symbol,String]
61
- # The identifying name for the config block.
62
- #
63
- # @param block [Proc]
64
- # Code block for configuration.
65
- #
66
- # @return [Proc] code block
67
- def self.[]=(name, block)
68
- config[name.to_sym] = block.to_proc
69
- end
70
-
71
- # Read config file.
72
- #
73
- # @return [String] contents of the `.conf.rb` file
74
- def self.read
75
- File.read(file)
76
- end
77
-
78
- # Find config file by looking up the '.conf.rb' file.
79
- #
80
- # @param dir [String]
81
- # Optional directory to begin search.
82
- #
83
- # @return [String] file path
84
- def self.file(dir=nil)
85
- dir = dir || Dir.pwd
86
- while dir != '/'
87
- if file = Dir.glob(File.join(dir,filename),File::FNM_CASEFOLD).first
88
- return file
89
- end
90
- dir = File.dirname(dir)
91
- end
92
- nil
93
- end
6
+ require 'finder'
7
+ require 'yaml'
8
+ require 'ostruct'
94
9
 
95
- # Root directory, where config file is located.
96
- #
97
- # @param dir [String]
98
- # Optional directory to begin search.
99
- #
100
- # @return [String] directory path
101
- def self.root(dir=nil)
102
- f = file(dir)
103
- f ? File.dirname(f) : nil
104
- end
10
+ require 'confection/basic_object'
11
+ require 'confection/core_ext'
12
+ require 'confection/project'
13
+ require 'confection/store'
14
+ require 'confection/dsl'
15
+ require 'confection/hash_builder'
16
+ require 'confection/config'
17
+ require 'confection/controller'
18
+ require 'confection/current'
105
19
 
106
- # The Evaluator class is used to evaluate the `.co.rb` file.
107
- #
108
- class Evaluator < Module #BasicObject
109
- def self.binding
110
- new.__binding__
111
- end
112
- def __binding__
113
- binding
114
- end
115
- def method_missing(sym, *args, &block)
116
- #def block.call
117
- # ::Kernel.eval('self',::TOPLEVEL_BINDING).instance_exec(&self)
118
- #end
119
- ::Confection[sym] = block
120
- end
121
- end
20
+ #
21
+ # Confection's primary use method, lookups a configuration
22
+ # given the tool and profile.
23
+ #
24
+ # To select all profiles for a given tool, use `'*'`.
25
+ #
26
+ # @return [Confection::Controller] config controller
27
+ #
28
+ def config(tool, *options)
29
+ Confection.controller(self, tool, *options)
30
+ end
122
31
 
123
- # The Controller class is used to encapsulate the two types of invocation
124
- # that are posible on configuration blocks.
125
- #
126
- class Controller
127
- def initialize(scope, &block)
128
- @scope = scope
129
- @block = block
130
- end
131
- def exec(*args) # should this be named #call instead?
132
- @scope.instance_exec(*args, &@block)
133
- end
134
- def call(*args)
135
- ::Kernel.eval('self',::TOPLEVEL_BINDING).instance_exec(*args, &@block)
136
- end
137
- def to_proc
138
- @block
139
- end
140
- end
32
+ #
33
+ # Alias for #config.
34
+ #
35
+ alias confection config
141
36
 
142
- class NullController
143
- def exec(*); end
144
- def call(*); end
145
- def to_proc; Proc.new{}; end
146
- end
37
+ #
38
+ #
39
+ #
40
+ def configure(tool, *options)
41
+ controller = Confection.controller(self, tool, *options)
42
+ controller.configure
147
43
  end
148
44
 
149
- # Confection's primary use method.
150
45
  #
151
- # @return [Confection::Controller] config controller
152
- def confection(name, *args)
153
- config_block = Confection[name.to_sym]
154
- if config_block
155
- Confection::Controller.new(self, &config_block)
156
- else
157
- #warn "no configuration -- `#{name}'"
158
- Confection::NullController.new
159
- end
160
- end
46
+ # Alias for #configure.
47
+ #
48
+ alias confect configure
161
49
 
162
50
  # Copyright (c) 2011 Rubyworks (BSD-2-Clause)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: confection
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
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: 2011-11-18 00:00:00.000000000 Z
12
+ date: 2012-03-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: blankslate
16
- requirement: &26062180 !ruby/object:Gem::Requirement
15
+ name: finder
16
+ requirement: &70312239870960 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,32 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *26062180
24
+ version_requirements: *70312239870960
25
+ - !ruby/object:Gem::Dependency
26
+ name: facets
27
+ requirement: &70312239886780 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70312239886780
36
+ - !ruby/object:Gem::Dependency
37
+ name: blankslate
38
+ requirement: &70312239886280 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70312239886280
25
47
  - !ruby/object:Gem::Dependency
26
48
  name: detroit
27
- requirement: &26077440 !ruby/object:Gem::Requirement
49
+ requirement: &70312239885780 !ruby/object:Gem::Requirement
28
50
  none: false
29
51
  requirements:
30
52
  - - ! '>='
@@ -32,10 +54,21 @@ dependencies:
32
54
  version: '0'
33
55
  type: :development
34
56
  prerelease: false
35
- version_requirements: *26077440
57
+ version_requirements: *70312239885780
36
58
  - !ruby/object:Gem::Dependency
37
59
  name: qed
38
- requirement: &26076620 !ruby/object:Gem::Requirement
60
+ requirement: &70312239885280 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70312239885280
69
+ - !ruby/object:Gem::Dependency
70
+ name: ae
71
+ requirement: &70312239884780 !ruby/object:Gem::Requirement
39
72
  none: false
40
73
  requirements:
41
74
  - - ! '>='
@@ -43,24 +76,27 @@ dependencies:
43
76
  version: '0'
44
77
  type: :development
45
78
  prerelease: false
46
- version_requirements: *26076620
79
+ version_requirements: *70312239884780
47
80
  description: Confection is a multi-tenant configuration system for Ruby projects.
48
81
  email:
49
82
  - transfire@gmail.com
50
83
  executables: []
51
84
  extensions: []
52
85
  extra_rdoc_files:
53
- - HISTORY.rdoc
54
- - README.rdoc
55
- - COPYING.rdoc
86
+ - LICENSE.txt
87
+ - HISTORY.md
88
+ - README.md
56
89
  files:
57
90
  - .ruby
58
91
  - .yardopts
59
92
  - lib/confection/basic_object.rb
93
+ - lib/confection/config.rb
94
+ - lib/confection/controller.rb
95
+ - lib/confection/dsl.rb
60
96
  - lib/confection.rb
61
- - HISTORY.rdoc
62
- - README.rdoc
63
- - COPYING.rdoc
97
+ - LICENSE.txt
98
+ - HISTORY.md
99
+ - README.md
64
100
  homepage: http://rubyworks.github.com/confection
65
101
  licenses:
66
102
  - BSD-2-Clause
@@ -82,7 +118,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
82
118
  version: '0'
83
119
  requirements: []
84
120
  rubyforge_project:
85
- rubygems_version: 1.8.10
121
+ rubygems_version: 1.8.11
86
122
  signing_key:
87
123
  specification_version: 3
88
124
  summary: Multi-tenant configuration for Ruby
data/COPYING.rdoc DELETED
@@ -1,31 +0,0 @@
1
- = COPYRIGHT NOTICES
2
-
3
- == Confection
4
-
5
- Copyright:: (c) 2011 Rubyworks
6
- License:: BSD-2-Clause
7
- Website:: http://rubyworks.github.com/tapout
8
-
9
- Copyright 2011 Rubyworks. All rights reserved.
10
-
11
- Redistribution and use in source and binary forms, with or without
12
- modification, are permitted provided that the following conditions are met:
13
-
14
- 1. Redistributions of source code must retain the above copyright notice,
15
- this list of conditions and the following disclaimer.
16
-
17
- 2. Redistributions in binary form must reproduce the above copyright
18
- notice, this list of conditions and the following disclaimer in the
19
- documentation and/or other materials provided with the distribution.
20
-
21
- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
22
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
23
- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24
- COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25
- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26
- NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
28
- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30
- EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
-
data/README.rdoc DELETED
@@ -1,83 +0,0 @@
1
- = Confection
2
-
3
- {Homepage}[http://rubyworks.github.com/confection] |
4
- {Source Code}[http://github.com/rubyworks/confection] |
5
- {Report Issue}[http://github.com/rubyworks/confection/issues] |
6
- {Mailing List}[http://googlegroups.com/group/rubyworks-mailinglist]
7
-
8
- {<img src="http://travis-ci.org/rubyworks/confection.png" />}[http://travis-ci.org/rubyworks/confection]
9
-
10
-
11
- == Description
12
-
13
- Confection is multi-tenant configuration system for Ruby projects. If was
14
- designed to facilitate Ruby-based configuration for multiple tools in a
15
- single file. It is extremely simple, which makes it easy to understand
16
- and flexible in use.
17
-
18
-
19
- == Synopsis
20
-
21
- Create a file in you project called `Confile`. By default the file can have any
22
- name tha matches the glob `{.,}confile{.rb,}` case insensitive. In this file
23
- add configuration blocks by name. For example, let's demonstrate how we could
24
- use this to configure Rake tasks.
25
-
26
- $ cat Confile
27
- rake do
28
- desc 'generate yard docs'
29
- task :yard do
30
- sh 'yard'
31
- end
32
- end
33
-
34
- In our Rakefile:
35
-
36
- $ cat Rakefile
37
- require 'confection'
38
- confection(:rake).call
39
-
40
- Now you might wonder why the heck you would do this. That's where the *multi-tenancy*
41
- comes into play. Let's add another configuration, and this time for a tool that has
42
- native support for Confection.
43
-
44
- $ cat Confile
45
- title = "myapp"
46
-
47
- rake do
48
- desc 'generate yard docs'
49
- task :yard do
50
- sh "yard doc --title #{title}"
51
- end
52
- end
53
-
54
- qed do |config|
55
- config.title = "#{title} Demonstrandum"
56
- end
57
-
58
- Now we have configuration for both the rake tool and the qed test tool in
59
- a single file. Thus we gain the advantage of reducing the file count of our
60
- project while pulling our tool configurations together into one place.
61
- Moreover, these configurations can potentially share settings as demonstrated
62
- here via the `title` variable.
63
-
64
- Using Confection in your libraries is very simple. As you can see from our
65
- example Rakefile. The `#confection` method is used to get a handle on a named
66
- configuration. With it you have two options, `#call` or `#exec`. The first
67
- evaluates the configuration block at the toplevel, while the later evaluates
68
- the block in the context of the caller.
69
-
70
-
71
- == Release Notes
72
-
73
- Please see HISTORY.rdoc file.
74
-
75
-
76
- == Copyrights
77
-
78
- Copyright (c) 2011 Rubyworks
79
-
80
- Confection is distributable in accordance with the terms of the *BSD-2-Clause* license.
81
-
82
- See COPYING.rdoc for details.
83
-