confection 0.1.0 → 0.2.0
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/.ruby +14 -5
- data/{HISTORY.rdoc → HISTORY.md} +19 -4
- data/LICENSE.txt +27 -0
- data/README.md +149 -0
- data/lib/confection/basic_object.rb +2 -0
- data/lib/confection/config.rb +170 -0
- data/lib/confection/controller.rb +175 -0
- data/lib/confection/dsl.rb +154 -0
- data/lib/confection.rb +37 -149
- metadata +52 -16
- data/COPYING.rdoc +0 -31
- data/README.rdoc +0 -83
data/.ruby
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
---
|
2
2
|
source:
|
3
|
-
-
|
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.
|
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: '
|
54
|
+
date: '2012-03-11'
|
data/{HISTORY.rdoc → HISTORY.md}
RENAMED
@@ -1,6 +1,21 @@
|
|
1
|
-
|
1
|
+
# RELEASE HISTORY
|
2
2
|
|
3
|
-
|
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
|
-
|
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
|
-
|
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
|
+
[](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
|
+
|
@@ -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
|
-
|
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
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
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
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
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
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
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
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
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
|
-
#
|
152
|
-
|
153
|
-
|
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.
|
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:
|
12
|
+
date: 2012-03-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
16
|
-
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: *
|
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: &
|
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: *
|
57
|
+
version_requirements: *70312239885780
|
36
58
|
- !ruby/object:Gem::Dependency
|
37
59
|
name: qed
|
38
|
-
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: *
|
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
|
-
-
|
54
|
-
-
|
55
|
-
-
|
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
|
-
-
|
62
|
-
-
|
63
|
-
-
|
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.
|
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
|
-
|