blindgaenger-configurable 0.1
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/README.textile +203 -0
- data/Rakefile +13 -0
- data/examples/brecht.rb +40 -0
- data/examples/computers.config +16 -0
- data/examples/computers.rb +46 -0
- data/examples/triangle.rb +32 -0
- data/examples/website.rb +22 -0
- data/lib/configurable.rb +70 -0
- metadata +68 -0
data/README.textile
ADDED
@@ -0,0 +1,203 @@
|
|
1
|
+
h1. Configurable
|
2
|
+
|
3
|
+
Little helper to configure ruby instances in a DSLish way.
|
4
|
+
|
5
|
+
|
6
|
+
h2. Usage
|
7
|
+
|
8
|
+
See the @examples/triangle.rb@ for the example described here.
|
9
|
+
|
10
|
+
Include it in your class and define some configuration attributes:
|
11
|
+
|
12
|
+
<pre><code>
|
13
|
+
require 'rubygems'
|
14
|
+
require 'configurable'
|
15
|
+
|
16
|
+
class Triangle
|
17
|
+
include Configurable
|
18
|
+
|
19
|
+
config_accessor :shape
|
20
|
+
config_accessor :color
|
21
|
+
end
|
22
|
+
</code></pre>
|
23
|
+
|
24
|
+
Configure some instances. Each config needs a @key@ to be accessible beside all
|
25
|
+
the other configs. Let's name it after some important mathematics.
|
26
|
+
|
27
|
+
<pre><code>
|
28
|
+
Triangle.configure 'euklid' do
|
29
|
+
shape 'isosceles'
|
30
|
+
color 'red'
|
31
|
+
end
|
32
|
+
|
33
|
+
Triangle.configure 'pythagoras' do
|
34
|
+
shape 'equilateral'
|
35
|
+
color 'blue'
|
36
|
+
end
|
37
|
+
</code></pre>
|
38
|
+
|
39
|
+
Use the configured instances.
|
40
|
+
|
41
|
+
<pre><code>
|
42
|
+
Triangle.configs #=> {"euclid"=>#<Triangle:0x...>, "pythagoras"=>#<Triangle:0x...>}
|
43
|
+
|
44
|
+
Triangle.each {|name, triangle|
|
45
|
+
puts "#{name} => #{triangle.inspect}"
|
46
|
+
}
|
47
|
+
|
48
|
+
Triangle['pythagoras'].shape #=> equilateral
|
49
|
+
</code></pre>
|
50
|
+
|
51
|
+
Of course, feel free to have a look at the "source code":http://github.com/blindgaenger/configurable on Github. ;)
|
52
|
+
|
53
|
+
|
54
|
+
h3. Initalize with the configured key
|
55
|
+
|
56
|
+
In some cases the key you use in the @configure@ method should be available in
|
57
|
+
the model as well. Of course, you could specify it again, but that's not necessary.
|
58
|
+
|
59
|
+
Just define (or maybe you already have) a contructor which is able to receive
|
60
|
+
the specified key. It's up to you, what you do with it.
|
61
|
+
|
62
|
+
<pre><code>
|
63
|
+
class Website
|
64
|
+
include Configurable
|
65
|
+
|
66
|
+
config_accessor :name
|
67
|
+
config_accessor :url
|
68
|
+
|
69
|
+
def initialize(key)
|
70
|
+
@name = key
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
Website.configure 'StackOverflow' do
|
75
|
+
url 'http://stackoverflow.com/'
|
76
|
+
end
|
77
|
+
|
78
|
+
so = Website['StackOverflow']
|
79
|
+
so.name #=> StackOverflow
|
80
|
+
so.url #=> http://stackoverflow.com/
|
81
|
+
</code></pre>
|
82
|
+
|
83
|
+
|
84
|
+
h3. Reader, writer or accessor
|
85
|
+
|
86
|
+
The basic @attr_*@ methods are available as @config_*@. They create the getter
|
87
|
+
and setter methods as usual. So you can still define which attributes should be
|
88
|
+
accessible from the outside world.
|
89
|
+
|
90
|
+
<pre><code>
|
91
|
+
class Person
|
92
|
+
include Configurable
|
93
|
+
|
94
|
+
config_reader :birthday # can't change it
|
95
|
+
config_writer :nickname # don't even know how they call you
|
96
|
+
config_accessor :friends # may come and go
|
97
|
+
end
|
98
|
+
|
99
|
+
Person.configure 'Bertolt Brecht' do
|
100
|
+
birthday '1898-02-10'
|
101
|
+
nickname 'Bert'
|
102
|
+
friends 'Hanns Eisler', 'Karl Valentin'
|
103
|
+
end
|
104
|
+
|
105
|
+
brecht = Person['Bertolt Brecht']
|
106
|
+
|
107
|
+
# reader
|
108
|
+
brecht.birthday #=> 1898-02-10
|
109
|
+
begin
|
110
|
+
brecht.birthday = '2008-12-24'
|
111
|
+
rescue NoMethodError => ex
|
112
|
+
end
|
113
|
+
|
114
|
+
# writer
|
115
|
+
brecht.nickname = 'Herr K.'
|
116
|
+
begin
|
117
|
+
brecht.nickname
|
118
|
+
rescue NoMethodError => ex
|
119
|
+
end
|
120
|
+
|
121
|
+
# accessor
|
122
|
+
brecht.friends #=> ["Hanns Eisler", "Karl Valentin"]
|
123
|
+
brecht.friends << 'Carola Neher'
|
124
|
+
brecht.friends #=> ["Hanns Eisler", "Karl Valentin", "Carola Neher"]
|
125
|
+
</code></pre>
|
126
|
+
|
127
|
+
You see, all behave the exact same way!
|
128
|
+
|
129
|
+
|
130
|
+
h3. Use in configuration files
|
131
|
+
|
132
|
+
Please see @examples/computers.rb@ for the working example.
|
133
|
+
|
134
|
+
Ok, at first define the model. Please note, that @type@ is the second parameter
|
135
|
+
of the constructor.
|
136
|
+
|
137
|
+
<pre><code>
|
138
|
+
class Computer
|
139
|
+
include Configurable
|
140
|
+
|
141
|
+
config_accessor :host
|
142
|
+
config_accessor :type
|
143
|
+
config_accessor :ip
|
144
|
+
|
145
|
+
def initialize(host, type)
|
146
|
+
@host = host
|
147
|
+
@type = type
|
148
|
+
end
|
149
|
+
end
|
150
|
+
</code></pre>
|
151
|
+
|
152
|
+
Now define some DSLish config helpers. Each injects a different @type@ as
|
153
|
+
arguments to the @configure@ methods. Use as much arguments as you like. But it's
|
154
|
+
important, that the @key@ (in this case the @name@) is still the first argument.
|
155
|
+
|
156
|
+
<pre><code>
|
157
|
+
def server(name, &block)
|
158
|
+
Computer.configure(name, :server, &block)
|
159
|
+
end
|
160
|
+
|
161
|
+
def notebook(name, &block)
|
162
|
+
Computer.configure(name, :notebook, &block)
|
163
|
+
end
|
164
|
+
</code></pre>
|
165
|
+
|
166
|
+
Create a config file and use the DSL. Although the helpers simply wrap the
|
167
|
+
@configure@ method it looks much nicer!
|
168
|
+
|
169
|
+
<pre><code>
|
170
|
+
server 'raumstation' do
|
171
|
+
ip '192.168.0.201'
|
172
|
+
end
|
173
|
+
|
174
|
+
server 'wohnserver' do
|
175
|
+
ip '192.168.0.202'
|
176
|
+
end
|
177
|
+
|
178
|
+
notebook 'gartenstuhl' do
|
179
|
+
ip '192.168.0.203'
|
180
|
+
end
|
181
|
+
</code></pre>
|
182
|
+
|
183
|
+
Back in your ruby file, load the config and use it as usual.
|
184
|
+
|
185
|
+
<pre><code>
|
186
|
+
config_file = 'computers.config'
|
187
|
+
load config_file
|
188
|
+
|
189
|
+
ips = Computer.map {|name, computer| computer.ip }
|
190
|
+
#=> ["192.168.0.201", "192.168.0.200", "192.168.0.202", "192.168.0.203"]
|
191
|
+
|
192
|
+
raumstation = Computer['raumstation']
|
193
|
+
raumstation.type #=> :server
|
194
|
+
</code></pre>
|
195
|
+
|
196
|
+
That's it!
|
197
|
+
|
198
|
+
|
199
|
+
h2. Contact
|
200
|
+
|
201
|
+
You can contact me via mail at blindgaenger at gmail dot com, or leave me a
|
202
|
+
message on my "Github profile":http://github.com/blindgaenger.
|
203
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec/rake/spectask'
|
2
|
+
|
3
|
+
desc "Run Specs with Rspec"
|
4
|
+
Spec::Rake::SpecTask.new :spec do |t|
|
5
|
+
t.spec_opts = %w(--format specdoc --color)
|
6
|
+
t.spec_files = FileList['spec/*_spec.rb']
|
7
|
+
end
|
8
|
+
|
9
|
+
$:.unshift(File.dirname(__FILE__) + '/../../lib')
|
10
|
+
require 'cucumber/rake/task'
|
11
|
+
Cucumber::Rake::Task.new do |t|
|
12
|
+
t.cucumber_opts = "--format pretty --no-source"
|
13
|
+
end
|
data/examples/brecht.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
$:.unshift File.join(File::dirname(__FILE__), '..', 'lib')
|
2
|
+
require 'configurable'
|
3
|
+
|
4
|
+
class Person
|
5
|
+
include Configurable
|
6
|
+
|
7
|
+
config_reader :birthday # can't change it
|
8
|
+
config_writer :nickname # don't even know how they call you
|
9
|
+
config_accessor :friends # may come and go
|
10
|
+
end
|
11
|
+
|
12
|
+
Person.configure 'Bertolt Brecht' do
|
13
|
+
birthday '1898-02-10'
|
14
|
+
nickname 'Bert'
|
15
|
+
friends 'Hanns Eisler', 'Karl Valentin'
|
16
|
+
end
|
17
|
+
|
18
|
+
brecht = Person['Bertolt Brecht']
|
19
|
+
|
20
|
+
# reader
|
21
|
+
brecht.birthday #=> 1898-02-10
|
22
|
+
begin
|
23
|
+
brecht.birthday = '2008-12-24'
|
24
|
+
rescue NoMethodError => ex
|
25
|
+
#=> undefined method `birthday=' for #<Person:0xb7c30d04>
|
26
|
+
end
|
27
|
+
|
28
|
+
# writer
|
29
|
+
brecht.nickname = 'Herr K.'
|
30
|
+
begin
|
31
|
+
brecht.nickname
|
32
|
+
rescue NoMethodError => ex
|
33
|
+
#=> super: no superclass method `nickname'
|
34
|
+
end
|
35
|
+
|
36
|
+
# accessor
|
37
|
+
brecht.friends #=> ["Hanns Eisler", "Karl Valentin"]
|
38
|
+
brecht.friends << 'Carola Neher'
|
39
|
+
brecht.friends #=> ["Hanns Eisler", "Karl Valentin", "Carola Neher"]
|
40
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
$:.unshift File.join(File::dirname(__FILE__), '..', 'lib')
|
2
|
+
require 'configurable'
|
3
|
+
|
4
|
+
class Computer
|
5
|
+
include Configurable
|
6
|
+
|
7
|
+
attr_accessor :type
|
8
|
+
config_accessor :hostname
|
9
|
+
config_accessor :ip
|
10
|
+
|
11
|
+
def initialize(host, type)
|
12
|
+
@hostname = host
|
13
|
+
@type = type
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
# define some DSLish config helpers
|
19
|
+
|
20
|
+
def server(name, &block)
|
21
|
+
Computer.configure(name, :server, &block)
|
22
|
+
end
|
23
|
+
|
24
|
+
def desktop(name, &block)
|
25
|
+
Computer.configure(name, :desktop, &block)
|
26
|
+
end
|
27
|
+
|
28
|
+
def notebook(name, &block)
|
29
|
+
Computer.configure(name, :notebook, &block)
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
# load the config (here from 'computers.config')
|
34
|
+
config_file = $0.gsub /#{File.extname($0)}$/, '.config'
|
35
|
+
load config_file
|
36
|
+
|
37
|
+
|
38
|
+
# now use them
|
39
|
+
|
40
|
+
ips = Computer.map {|name, computer| computer.ip }
|
41
|
+
#=> ["192.168.0.201", "192.168.0.200", "192.168.0.202", "192.168.0.203"]
|
42
|
+
|
43
|
+
Computer['raumstation'] #=> <Computer:0xb7c6e4c4 @type=:server, @hostname="raumstation", @ip="192.168.0.201">
|
44
|
+
Computer['apfelsaft'] #=> <Computer:0xb7c6e62c @type=:desktop, @hostname="apfelsaft", @ip="192.168.0.200">
|
45
|
+
Computer['wohnserver'] #=> <Computer:0xb7c6e370 @type=:server, @hostname="wohnserver", @ip="192.168.0.202">
|
46
|
+
Computer['gartenstuhl'] #=> <Computer:0xb7c6e21c @type=:notebook, @hostname="gartenstuhl", @ip="192.168.0.203">
|
@@ -0,0 +1,32 @@
|
|
1
|
+
$:.unshift File.join(File::dirname(__FILE__), '..', 'lib')
|
2
|
+
require 'configurable'
|
3
|
+
|
4
|
+
class Triangle
|
5
|
+
include Configurable
|
6
|
+
|
7
|
+
config_accessor :shape
|
8
|
+
|
9
|
+
config_accessor :sides do |*args|
|
10
|
+
args.join('->')
|
11
|
+
end
|
12
|
+
|
13
|
+
config_accessor :angles do |alpha, beta, gamma, *others|
|
14
|
+
raise 'more than 3 angles defined' unless others.empty?
|
15
|
+
raise 'sum of all angels is not 180' if alpha + beta + gamma != 180
|
16
|
+
[alpha, beta, gamma]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
Triangle.configure('euclid') do
|
21
|
+
shape 'isosceles'
|
22
|
+
sides 'a', 'b', 'c'
|
23
|
+
angles 90, 60, 30
|
24
|
+
end
|
25
|
+
|
26
|
+
p Triangle.configs
|
27
|
+
#=> {"euclid"=>#<Triangle:0xb7d01e90 @sides="a->b->c", @shape="isosceles", @angles=[90, 60, 30]>}
|
28
|
+
|
29
|
+
triangle = Triangle['euclid']
|
30
|
+
p triangle.sides
|
31
|
+
#=> "a->b->c"
|
32
|
+
|
data/examples/website.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
$:.unshift File.join(File::dirname(__FILE__), '..', 'lib')
|
2
|
+
require 'configurable'
|
3
|
+
|
4
|
+
class Website
|
5
|
+
include Configurable
|
6
|
+
|
7
|
+
config_accessor :name
|
8
|
+
config_accessor :url
|
9
|
+
|
10
|
+
def initialize(key)
|
11
|
+
@name = key
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Website.configure 'StackOverflow' do
|
16
|
+
url 'http://stackoverflow.com/'
|
17
|
+
end
|
18
|
+
|
19
|
+
so = Website['StackOverflow']
|
20
|
+
so.name #=> StackOverflow
|
21
|
+
so.url #=> http://stackoverflow.com/
|
22
|
+
|
data/lib/configurable.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
module Configurable
|
2
|
+
|
3
|
+
def self.included(base)
|
4
|
+
|
5
|
+
class << base
|
6
|
+
attr_reader :configs
|
7
|
+
include Enumerable
|
8
|
+
def method_missing(name, *args, &block)
|
9
|
+
@configs ||= {}
|
10
|
+
@configs.send(name, *args, &block)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
# based on http://eigenclass.org/hiki.rb?ruby+plugins
|
16
|
+
def base.config_attr(reader, writer, *names, &block)
|
17
|
+
class_eval do
|
18
|
+
names.each do |name|
|
19
|
+
|
20
|
+
define_method(name) do |*args|
|
21
|
+
if args.empty?
|
22
|
+
if reader
|
23
|
+
instance_variable_get("@#{name}")
|
24
|
+
else
|
25
|
+
super # should raise the error
|
26
|
+
end
|
27
|
+
else
|
28
|
+
value = *args
|
29
|
+
value = block.call(*args) if block_given?
|
30
|
+
instance_variable_set("@#{name}", value)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
if writer
|
35
|
+
attr_writer name.to_sym
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def base.config_accessor(*names, &block)
|
43
|
+
config_attr(true, true, *names, &block)
|
44
|
+
end
|
45
|
+
|
46
|
+
def base.config_writer(*names, &block)
|
47
|
+
config_attr(false, true, *names, &block)
|
48
|
+
end
|
49
|
+
|
50
|
+
def base.config_reader(*names, &block)
|
51
|
+
config_attr(true, false, *names, &block)
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
def base.configure(key, *args, &block)
|
56
|
+
# arity isn't reliable, so just try it
|
57
|
+
begin
|
58
|
+
instance = self.new(key, *args)
|
59
|
+
rescue ArgumentError
|
60
|
+
instance = self.new(*args)
|
61
|
+
end
|
62
|
+
instance.instance_eval &block
|
63
|
+
self[key] = instance
|
64
|
+
instance
|
65
|
+
end
|
66
|
+
|
67
|
+
end # self.included
|
68
|
+
|
69
|
+
end
|
70
|
+
|
metadata
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: blindgaenger-configurable
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "0.1"
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- blindgaenger
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-01-18 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: cucumber
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.1.15
|
23
|
+
version:
|
24
|
+
description:
|
25
|
+
email: blindgaenger@gmail.com
|
26
|
+
executables: []
|
27
|
+
|
28
|
+
extensions: []
|
29
|
+
|
30
|
+
extra_rdoc_files: []
|
31
|
+
|
32
|
+
files:
|
33
|
+
- Rakefile
|
34
|
+
- README.textile
|
35
|
+
- lib/configurable.rb
|
36
|
+
- examples/brecht.rb
|
37
|
+
- examples/computers.config
|
38
|
+
- examples/computers.rb
|
39
|
+
- examples/triangle.rb
|
40
|
+
- examples/website.rb
|
41
|
+
has_rdoc: "false"
|
42
|
+
homepage: http://github.com/blindgaenger/configurable
|
43
|
+
post_install_message:
|
44
|
+
rdoc_options: []
|
45
|
+
|
46
|
+
require_paths:
|
47
|
+
- lib
|
48
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: "0"
|
53
|
+
version:
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: "0"
|
59
|
+
version:
|
60
|
+
requirements: []
|
61
|
+
|
62
|
+
rubyforge_project:
|
63
|
+
rubygems_version: 1.2.0
|
64
|
+
signing_key:
|
65
|
+
specification_version: 2
|
66
|
+
summary: Little helper to configure ruby instances in a DSLish way.
|
67
|
+
test_files: []
|
68
|
+
|