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 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
@@ -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,16 @@
1
+
2
+ desktop 'apfelsaft' do
3
+ ip '192.168.0.200'
4
+ end
5
+
6
+ server 'raumstation' do
7
+ ip '192.168.0.201'
8
+ end
9
+
10
+ server 'wohnserver' do
11
+ ip '192.168.0.202'
12
+ end
13
+
14
+ notebook 'gartenstuhl' do
15
+ ip '192.168.0.203'
16
+ end
@@ -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
+
@@ -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
+
@@ -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
+