volute 0.1.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/CHANGELOG.txt ADDED
@@ -0,0 +1,6 @@
1
+
2
+ = volute - CHANGELOG.txt
3
+
4
+
5
+ == volute - 0.1.0 not yet released
6
+
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+
2
+ Copyright (c) 2010-2010, John Mettraux, jmettraux@gmail.com
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in
12
+ all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ THE SOFTWARE.
21
+
data/README.rdoc ADDED
@@ -0,0 +1,142 @@
1
+
2
+ = volute
3
+
4
+ It could be a 'set event bus', or a 'business logic relocator'.
5
+
6
+ It can be used to implement toy state machines, or dumb rule systems.
7
+
8
+ See examples/ and specs/
9
+
10
+
11
+ == usage
12
+
13
+ gem install volute
14
+
15
+
16
+ == example : equation
17
+
18
+ # license is MIT
19
+
20
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
21
+
22
+ require 'volute'
23
+
24
+ #
25
+ # our class
26
+
27
+ class Equation
28
+ include Volute
29
+
30
+ attr_accessor :km, :h, :kph
31
+
32
+ def initialize
33
+ @km = 1.0
34
+ @h = 1.0
35
+ @kph = 1.0
36
+ end
37
+
38
+ def inspect
39
+
40
+ "#{@km} km, #{@h} h, #{@kph} kph"
41
+ end
42
+ end
43
+
44
+ #
45
+ # a volute triggered for any 'set' operation on an attribute of book
46
+
47
+ volute Equation do
48
+
49
+ # object.vset(:state, x)
50
+ # is equivalent to
51
+ # object.instance_variable_set(:@state, x)
52
+
53
+ volute :km do
54
+ object.vset(:h, value / object.kph)
55
+ end
56
+ volute :h do
57
+ object.vset(:kph, object.km / value)
58
+ end
59
+ volute :kph do
60
+ object.vset(:h, object.km / value)
61
+ end
62
+ end
63
+
64
+ #
65
+ # trying
66
+
67
+ e = Equation.new
68
+ p e # => 1.0 km, 1.0 h, 1.0 kph
69
+
70
+ e.kph = 10.0
71
+ p e # => 1.0 km, 0.1 h, 10.0 kph
72
+
73
+ e.km = 5.0
74
+ p e # => 5.0 km, 0.5 h, 10.0 kph
75
+
76
+
77
+ == example : some kind of state-machine
78
+
79
+ # license is MIT
80
+ #
81
+ # a state-machine-ish example, inspired by the example at
82
+ # http://github.com/qoobaa/transitions
83
+
84
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
85
+
86
+ require 'volute'
87
+
88
+ #
89
+ # our class
90
+
91
+ class Book
92
+ include Volute
93
+
94
+ attr_accessor :stock
95
+ attr_accessor :discontinued
96
+
97
+ attr_reader :state
98
+
99
+ def initialize (stock)
100
+ @stock = stock
101
+ @discontinued = false
102
+ @state = :in_stock
103
+ end
104
+ end
105
+
106
+ #
107
+ # a volute triggered for any 'set' operation on an attribute of book
108
+
109
+ volute Book do
110
+
111
+ # object.volute_do_set(:state, x)
112
+ # is equivalent to
113
+ # object.instance_variable_set(:@state, x)
114
+
115
+ if object.stock <= 0
116
+ object.volute_do_set(
117
+ :state, object.discontinued ? :discontinued : :out_of_stock)
118
+ else
119
+ object.volute_do_set(
120
+ :state, :in_stock)
121
+ end
122
+ end
123
+
124
+ #
125
+ # trying
126
+
127
+ emma = Book.new(10)
128
+
129
+ emma.stock = 2
130
+ p emma.state # => :in_stock
131
+
132
+ emma.stock = 0
133
+ p emma.state # => :out_of_stock
134
+
135
+ emma.discontinued = true
136
+ p emma.state # => :discontinued
137
+
138
+
139
+ == license
140
+
141
+ MIT, see LICENSE.txt
142
+
data/Rakefile ADDED
@@ -0,0 +1,86 @@
1
+
2
+ $:.unshift('.') # ruby 1.9.2
3
+
4
+ require 'lib/volute.rb'
5
+
6
+ require 'rubygems'
7
+ require 'rake'
8
+
9
+
10
+ #
11
+ # SPEC
12
+
13
+ task :spec do
14
+ sh "spec -cfs spec/"
15
+ end
16
+
17
+ task :default => :spec
18
+
19
+
20
+ #
21
+ # CLEAN
22
+
23
+ require 'rake/clean'
24
+ CLEAN.include('pkg', 'tmp', 'html', 'rdoc')
25
+
26
+
27
+ #
28
+ # GEM
29
+
30
+ require 'jeweler'
31
+
32
+ Jeweler::Tasks.new do |gem|
33
+
34
+ gem.version = Volute::VOLUTE_VERSION
35
+ gem.name = 'volute'
36
+ gem.summary = 'placing some [business] logic outside of classes'
37
+
38
+ gem.description = %{
39
+ placing some [business] logic outside of classes
40
+ }
41
+ gem.email = 'jmettraux@gmail.com'
42
+ gem.homepage = 'http://github.com/jmettraux/volute/'
43
+ gem.authors = [ 'John Mettraux' ]
44
+ gem.rubyforge_project = 'rufus'
45
+
46
+ #gem.test_file = 'test/test.rb'
47
+
48
+ #gem.add_dependency 'mime-types', '>= 1.16'
49
+ gem.add_development_dependency 'rake'
50
+ gem.add_development_dependency 'rspec'
51
+ gem.add_development_dependency 'jeweler'
52
+
53
+ # gemspec spec : http://www.rubygems.org/read/chapter/20
54
+ end
55
+ Jeweler::GemcutterTasks.new
56
+
57
+
58
+ #
59
+ # DOC
60
+
61
+ #
62
+ # make sure to have rdoc 2.5.x to run that
63
+ #
64
+ require 'rake/rdoctask'
65
+ Rake::RDocTask.new do |rd|
66
+
67
+ rd.main = 'README.rdoc'
68
+ rd.rdoc_dir = 'rdoc/volute'
69
+ rd.title = "volute #{Volute::VOLUTE_VERSION}"
70
+
71
+ rd.rdoc_files.include(
72
+ 'README.rdoc', 'CHANGELOG.txt', 'LICENSE.txt', 'lib/**/*.rb')
73
+ end
74
+
75
+
76
+ #
77
+ # TO THE WEB
78
+
79
+ task :upload_rdoc => [ :clean, :rdoc ] do
80
+
81
+ account = 'jmettraux@rubyforge.org'
82
+ webdir = '/var/www/gforge-projects/rufus'
83
+
84
+ sh "rsync -azv -e ssh rdoc/volute #{account}:#{webdir}/"
85
+ end
86
+
data/TODO.txt ADDED
@@ -0,0 +1,24 @@
1
+
2
+ [o] volute 'prev' => 'new' { ... }
3
+ [o] volute Module { ... }
4
+ [o] obj.volute_do_set(:a => 0, :b => 1)
5
+ [o] volute { over }
6
+
7
+ [ ] volute /^att/ { ... }
8
+ [ ] volute /regex/ => /regex/ { ... }
9
+
10
+ [ ] volute do
11
+ volute Invoice do
12
+ volute :paid do
13
+
14
+ if is(true)
15
+ object.comment = 'got paid'
16
+ elsif was(nil)
17
+ object.comment = 'still not paid'
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ [ ] multi-entity state machine example
24
+
@@ -0,0 +1,59 @@
1
+
2
+ # license is MIT
3
+
4
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
5
+
6
+ require 'volute'
7
+
8
+ #
9
+ # our class
10
+
11
+ class Equation
12
+ include Volute
13
+
14
+ attr_accessor :km, :h, :kph
15
+
16
+ def initialize
17
+ @km = 1.0
18
+ @h = 1.0
19
+ @kph = 1.0
20
+ end
21
+
22
+ def inspect
23
+
24
+ "#{@km} km, #{@h} h, #{@kph} kph"
25
+ end
26
+ end
27
+
28
+ #
29
+ # a volute triggered for any 'set' operation on an attribute of book
30
+
31
+ volute Equation do
32
+
33
+ # object.vset(:state, x)
34
+ # is equivalent to
35
+ # object.instance_variable_set(:@state, x)
36
+
37
+ volute :km do
38
+ object.vset(:h, value / object.kph)
39
+ end
40
+ volute :h do
41
+ object.vset(:kph, object.km / value)
42
+ end
43
+ volute :kph do
44
+ object.vset(:h, object.km / value)
45
+ end
46
+ end
47
+
48
+ #
49
+ # trying
50
+
51
+ e = Equation.new
52
+ p e # => 1.0 km, 1.0 h, 1.0 kph
53
+
54
+ e.kph = 10.0
55
+ p e # => 1.0 km, 0.1 h, 10.0 kph
56
+
57
+ e.km = 5.0
58
+ p e # => 5.0 km, 0.5 h, 10.0 kph
59
+
@@ -0,0 +1,60 @@
1
+
2
+ # license is MIT
3
+ #
4
+ # a state-machine-ish example, inspired by the example at
5
+ # http://github.com/qoobaa/transitions
6
+
7
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
8
+
9
+ require 'volute'
10
+
11
+ #
12
+ # our class
13
+
14
+ class Book
15
+ include Volute
16
+
17
+ attr_accessor :stock
18
+ attr_accessor :discontinued
19
+
20
+ attr_reader :state
21
+
22
+ def initialize (stock)
23
+ @stock = stock
24
+ @discontinued = false
25
+ @state = :in_stock
26
+ end
27
+ end
28
+
29
+ #
30
+ # a volute triggered for any 'set' operation on an attribute of book
31
+
32
+ volute Book do
33
+
34
+ # object.volute_do_set(:state, x)
35
+ # is equivalent to
36
+ # object.instance_variable_set(:@state, x)
37
+
38
+ if object.stock <= 0
39
+ object.volute_do_set(
40
+ :state, object.discontinued ? :discontinued : :out_of_stock)
41
+ else
42
+ object.volute_do_set(
43
+ :state, :in_stock)
44
+ end
45
+ end
46
+
47
+ #
48
+ # trying
49
+
50
+ emma = Book.new(10)
51
+
52
+ emma.stock = 2
53
+ p emma.state # => :in_stock
54
+
55
+ emma.stock = 0
56
+ p emma.state # => :out_of_stock
57
+
58
+ emma.discontinued = true
59
+ p emma.state # => :discontinued
60
+
data/lib/volute.rb ADDED
@@ -0,0 +1,171 @@
1
+ #--
2
+ # Copyright (c) 2010-2010, John Mettraux, jmettraux@gmail.com
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in
12
+ # all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ # THE SOFTWARE.
21
+ #
22
+ # Made in Japan.
23
+ #++
24
+
25
+ module Volute
26
+
27
+ VOLUTE_VERSION = '0.1.0'
28
+
29
+ #
30
+ # adding class methods to target classes
31
+
32
+ def self.included(target)
33
+
34
+ target.instance_eval do
35
+ alias o_attr_accessor attr_accessor
36
+ end
37
+
38
+ def target.attr_accessor(*args)
39
+
40
+ args.each do |arg|
41
+ define_method(arg) { volute_get(arg.to_s) }
42
+ define_method("#{arg}=") { |value| volute_set(arg.to_s, value) }
43
+ end
44
+ end
45
+ end
46
+
47
+ #
48
+ # instance methods added to target classes
49
+
50
+ def vset(key, value=nil)
51
+
52
+ if key.is_a?(Hash)
53
+ key.each { |k, v| instance_variable_set("@#{k}", v) }
54
+ else
55
+ instance_variable_set("@#{key}", value)
56
+ end
57
+ end
58
+
59
+ def volute_get(key)
60
+
61
+ instance_variable_get("@#{key}")
62
+ end
63
+
64
+ def volute_set(key, value)
65
+
66
+ previous_value = volute_get(key)
67
+ vset(key, value)
68
+ Volute.root_eval(self, key, previous_value, value)
69
+
70
+ value
71
+ end
72
+
73
+ #
74
+ # Volute class methods
75
+
76
+ def self.<<(block)
77
+
78
+ (@top ||= []) << block
79
+ end
80
+
81
+ # Nukes all the top level volutes.
82
+ #
83
+ def self.clear!
84
+
85
+ (@top = [])
86
+ end
87
+
88
+ def self.root_eval(object, attribute, previous_value, value)
89
+
90
+ target = Target.new(object, attribute, previous_value, value)
91
+
92
+ (@top || []).each { |args, block| target.volute(*args, &block) }
93
+ end
94
+
95
+ #
96
+ # some classes
97
+
98
+ class Target
99
+
100
+ attr_reader :object, :attribute, :previous_value, :value
101
+
102
+ def initialize(object, attribute, previous_value, value)
103
+
104
+ @object = object
105
+ @attribute = attribute
106
+ @previous_value = previous_value
107
+ @value = value
108
+
109
+ @over = false
110
+ end
111
+
112
+ def volute(*args, &block)
113
+
114
+ return if @over
115
+ return unless match?(args)
116
+
117
+ self.instance_eval(&block)
118
+ end
119
+
120
+ def over
121
+
122
+ @over = true
123
+ end
124
+
125
+ #def is(val)
126
+ # val == value
127
+ #end
128
+ #def was(val)
129
+ # val == previous_value
130
+ #end
131
+
132
+ protected
133
+
134
+ def match? (args)
135
+
136
+ classes = args.select { |a| a.is_a?(Class) }
137
+ args.select { |a| a.is_a?(Module) }.each { |m|
138
+ classes.concat(m.constants.collect { |c| m.const_get(c) })
139
+ }
140
+ if classes.size > 0 && (classes & object.class.ancestors).empty?
141
+ return false
142
+ end
143
+
144
+ atts = args.select { |a| a.is_a?(Symbol) }
145
+ if atts.size > 0 && ( ! atts.include?(attribute.to_sym))
146
+ return false
147
+ end
148
+
149
+ opts = args.last.is_a?(Hash) ? args.pop : {}
150
+
151
+ return true if opts.empty?
152
+
153
+ opts.inject(false) do |b, (k, v)|
154
+ b || (
155
+ (k == :any || k == previous_value) &&
156
+ (v == :any || v == value)
157
+ )
158
+ end
159
+
160
+ #rescue Exception => e
161
+ # p e
162
+ # e.backtrace.each { |l| p l }
163
+ end
164
+ end
165
+ end
166
+
167
+ def volute(*args, &block)
168
+
169
+ Volute << [ args, block ]
170
+ end
171
+
@@ -0,0 +1,44 @@
1
+
2
+ require File.join(File.dirname(__FILE__), 'spec_helper.rb')
3
+
4
+
5
+ describe Volute do
6
+
7
+ before(:each) do
8
+
9
+ @invoice = Invoice.new
10
+ @package = Package.new
11
+ end
12
+
13
+ describe 'when included' do
14
+
15
+ it 'should grant getters' do
16
+
17
+ @invoice.paid.should == nil
18
+ end
19
+
20
+ it 'should grants setters' do
21
+
22
+ @invoice.paid = true
23
+
24
+ @invoice.paid.should == true
25
+ end
26
+
27
+ it 'should allow setting in batch' do
28
+
29
+ @package.vset(:location => 'ZRH', :delivered => false)
30
+
31
+ @package.location.should == 'ZRH'
32
+ @package.delivered.should == false
33
+ end
34
+ end
35
+
36
+ describe 'setters' do
37
+
38
+ it 'should return the new value' do
39
+
40
+ (@invoice.paid = false).should == false
41
+ end
42
+ end
43
+ end
44
+
@@ -0,0 +1,48 @@
1
+
2
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+
4
+ require 'volute'
5
+
6
+ class Invoice
7
+ include Volute
8
+
9
+ attr_accessor :paid
10
+ o_attr_accessor :comment
11
+ end
12
+
13
+ class Item
14
+ include Volute
15
+
16
+ attr_accessor :delivered
17
+ o_attr_accessor :comment
18
+ end
19
+
20
+ class Package
21
+ include Volute
22
+
23
+ attr_accessor :location
24
+ attr_accessor :delivered
25
+ o_attr_accessor :comment
26
+ end
27
+
28
+ class Delivery
29
+ include Volute
30
+
31
+ attr_accessor :scheduled
32
+ attr_accessor :performed
33
+ o_attr_accessor :comment
34
+ end
35
+
36
+ module Financing
37
+ class Loan
38
+ include Volute
39
+ attr_accessor :price
40
+ o_attr_accessor :comment
41
+ end
42
+ class Grant
43
+ include Volute
44
+ attr_accessor :price
45
+ o_attr_accessor :comment
46
+ end
47
+ end
48
+
@@ -0,0 +1,189 @@
1
+
2
+ require File.join(File.dirname(__FILE__), 'spec_helper.rb')
3
+
4
+
5
+ describe 'a volute for a class' do
6
+
7
+ before(:each) do
8
+
9
+ Volute.clear!
10
+
11
+ @invoice = Invoice.new
12
+ @item = Item.new
13
+
14
+ volute Invoice do
15
+ object.comment = [ attribute, previous_value, value ]
16
+ end
17
+ end
18
+
19
+ it 'should affect its class' do
20
+
21
+ @invoice.paid = true
22
+
23
+ @invoice.comment.should == [ 'paid', nil, true ]
24
+ end
25
+
26
+ it 'should not affect other classes' do
27
+
28
+ @invoice.paid = true
29
+
30
+ @item.comment.should == nil
31
+ end
32
+ end
33
+
34
+ describe 'a volute for a module' do
35
+
36
+ before(:each) do
37
+
38
+ Volute.clear!
39
+
40
+ @invoice = Invoice.new
41
+
42
+ @loan = Financing::Loan.new
43
+ @grant = Financing::Grant.new
44
+
45
+ volute Financing do
46
+ object.comment = [ object.class, attribute, previous_value, value ]
47
+ end
48
+ end
49
+
50
+ it 'should not affect classes in other modules' do
51
+
52
+ @invoice.paid = false
53
+
54
+ @invoice.comment.should == nil
55
+ end
56
+
57
+ it 'should affect class A' do
58
+
59
+ @loan.price = '1 kopek'
60
+
61
+ @loan.comment.should == [ Financing::Loan, 'price', nil, '1 kopek' ]
62
+ end
63
+
64
+ it 'should affect class B' do
65
+
66
+ @grant.price = '1 cruzeiro'
67
+
68
+ @grant.comment.should == [ Financing::Grant, 'price', nil, '1 cruzeiro' ]
69
+ end
70
+ end
71
+
72
+
73
+ describe 'a volute for two classes' do
74
+
75
+ before(:each) do
76
+
77
+ Volute.clear!
78
+
79
+ @invoice = Invoice.new
80
+ @item = Item.new
81
+
82
+ volute Invoice, Item do
83
+ object.comment = [ attribute, previous_value, value ]
84
+ end
85
+ end
86
+
87
+ it 'should affect class A' do
88
+
89
+ @invoice.paid = true
90
+ @invoice.comment.should == [ 'paid', nil, true ]
91
+ end
92
+
93
+ it 'should affect class B' do
94
+
95
+ @item.delivered = true
96
+ @item.comment.should == [ 'delivered', nil, true ]
97
+ end
98
+ end
99
+
100
+ describe 'a volute for an attribute' do
101
+
102
+ before(:each) do
103
+
104
+ Volute.clear!
105
+
106
+ @item = Item.new
107
+ @package = Package.new
108
+
109
+ volute :delivered do
110
+ object.comment = [ object.class, attribute, previous_value, value ]
111
+ end
112
+ end
113
+
114
+ it 'should affect class A' do
115
+
116
+ @item.delivered = true
117
+
118
+ @item.comment.should == [ Item, 'delivered', nil, true ]
119
+ end
120
+
121
+ it 'should affect class B' do
122
+
123
+ @package.delivered = true
124
+
125
+ @package.comment.should == [ Package, 'delivered', nil, true ]
126
+ end
127
+ end
128
+
129
+ describe 'transition volutes' do
130
+
131
+ before(:each) do
132
+
133
+ Volute.clear!
134
+
135
+ @package = Package.new
136
+ @package.vset(:location, 'NRT')
137
+
138
+ volute :location, :any => 'SFO' do
139
+ object.comment = 'reached SFO'
140
+ end
141
+ volute :location, 'NRT' => 'SFO' do
142
+ object.comment = 'reached SFO from NRT'
143
+ end
144
+ volute 'NRT' => 'FCO' do
145
+ object.comment = 'reached FCO from NRT'
146
+ end
147
+ volute 'GVA' => :any do
148
+ object.comment = 'left GVA'
149
+ end
150
+ end
151
+
152
+ it 'should not trigger when not specified' do
153
+
154
+ @package.location = 'ZRH'
155
+
156
+ @package.comment.should == nil
157
+ end
158
+
159
+ it 'should trigger for an end state' do
160
+
161
+ @package.vset(:location, 'ZRH')
162
+ @package.location = 'SFO'
163
+
164
+ @package.comment.should == 'reached SFO'
165
+ end
166
+
167
+ it 'should trigger for an attribute, a start state and an end state' do
168
+
169
+ @package.location = 'SFO'
170
+
171
+ @package.comment.should == 'reached SFO from NRT'
172
+ end
173
+
174
+ it 'should trigger for a start state and an end state' do
175
+
176
+ @package.location = 'FCO'
177
+
178
+ @package.comment.should == 'reached FCO from NRT'
179
+ end
180
+
181
+ it 'should trigger for a start state' do
182
+
183
+ @package.vset(:location, 'GVA')
184
+ @package.location = 'CAL'
185
+
186
+ @package.comment.should == 'left GVA'
187
+ end
188
+ end
189
+
@@ -0,0 +1,97 @@
1
+
2
+ require File.join(File.dirname(__FILE__), 'spec_helper.rb')
3
+
4
+
5
+ describe 'a volute' do
6
+
7
+ before(:each) do
8
+
9
+ Volute.clear!
10
+
11
+ @invoice = Invoice.new
12
+
13
+ volute do
14
+ object.comment = [ attribute, previous_value, value ]
15
+ end
16
+ end
17
+
18
+ it 'should not be applied when #instance_variable_set is used' do
19
+
20
+ @invoice.instance_variable_set(:@paid, true)
21
+
22
+ @invoice.paid.should == true
23
+ @invoice.comment.should == nil
24
+ end
25
+
26
+ it 'should not be applied when #vset is used' do
27
+
28
+ @invoice.vset(:paid, true)
29
+
30
+ @invoice.comment.should == nil
31
+ end
32
+
33
+ describe 'with no arguments' do
34
+
35
+ it 'should be applied for any change' do
36
+
37
+ @invoice.paid = true
38
+
39
+ @invoice.paid.should == true
40
+ @invoice.comment.should == [ 'paid', nil, true ]
41
+ end
42
+ end
43
+ end
44
+
45
+ describe 'a class without a volute' do
46
+
47
+ before(:each) do
48
+
49
+ Volute.clear!
50
+
51
+ @invoice = Invoice.new
52
+ end
53
+
54
+ it 'should get as usual' do
55
+
56
+ @invoice.paid.should == nil
57
+ end
58
+
59
+ it 'should set as usual' do
60
+
61
+ (@invoice.paid = false).should == false
62
+ @invoice.paid.should == false
63
+ end
64
+ end
65
+
66
+ describe 'a volute with an over' do
67
+
68
+ before(:each) do
69
+
70
+ Volute.clear!
71
+
72
+ @package = Package.new
73
+
74
+ volute Package do
75
+ volute do
76
+ over if object.delivered
77
+ end
78
+ volute :location do
79
+ (object.comment ||= []) << value
80
+ end
81
+ end
82
+ end
83
+
84
+ it 'should prevent evaluation of further volutes' do
85
+
86
+ @package.location = 'ZRH'
87
+ @package.location = 'CDG'
88
+
89
+ @package.comment.should == %w[ ZRH CDG ]
90
+
91
+ @package.delivered = true
92
+ @package.location = 'FCO'
93
+
94
+ @package.comment.should == %w[ ZRH CDG ]
95
+ end
96
+ end
97
+
data/volute.gemspec ADDED
@@ -0,0 +1,70 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{volute}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["John Mettraux"]
12
+ s.date = %q{2010-10-08}
13
+ s.description = %q{
14
+ placing some [business] logic outside of classes
15
+ }
16
+ s.email = %q{jmettraux@gmail.com}
17
+ s.extra_rdoc_files = [
18
+ "LICENSE.txt",
19
+ "README.rdoc"
20
+ ]
21
+ s.files = [
22
+ "CHANGELOG.txt",
23
+ "LICENSE.txt",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "TODO.txt",
27
+ "examples/equation.rb",
28
+ "examples/state_machine.rb",
29
+ "lib/volute.rb",
30
+ "spec/include_volute_spec.rb",
31
+ "spec/spec_helper.rb",
32
+ "spec/volute_guard_spec.rb",
33
+ "spec/volute_spec.rb",
34
+ "volute.gemspec"
35
+ ]
36
+ s.homepage = %q{http://github.com/jmettraux/volute/}
37
+ s.rdoc_options = ["--charset=UTF-8"]
38
+ s.require_paths = ["lib"]
39
+ s.rubyforge_project = %q{rufus}
40
+ s.rubygems_version = %q{1.3.5}
41
+ s.summary = %q{placing some [business] logic outside of classes}
42
+ s.test_files = [
43
+ "spec/include_volute_spec.rb",
44
+ "spec/spec_helper.rb",
45
+ "spec/volute_guard_spec.rb",
46
+ "spec/volute_spec.rb",
47
+ "examples/equation.rb",
48
+ "examples/state_machine.rb"
49
+ ]
50
+
51
+ if s.respond_to? :specification_version then
52
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
53
+ s.specification_version = 3
54
+
55
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
56
+ s.add_development_dependency(%q<rake>, [">= 0"])
57
+ s.add_development_dependency(%q<rspec>, [">= 0"])
58
+ s.add_development_dependency(%q<jeweler>, [">= 0"])
59
+ else
60
+ s.add_dependency(%q<rake>, [">= 0"])
61
+ s.add_dependency(%q<rspec>, [">= 0"])
62
+ s.add_dependency(%q<jeweler>, [">= 0"])
63
+ end
64
+ else
65
+ s.add_dependency(%q<rake>, [">= 0"])
66
+ s.add_dependency(%q<rspec>, [">= 0"])
67
+ s.add_dependency(%q<jeweler>, [">= 0"])
68
+ end
69
+ end
70
+
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: volute
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - John Mettraux
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-10-08 00:00:00 +09:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rake
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: rspec
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: jeweler
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ description: "\n\
46
+ placing some [business] logic outside of classes\n "
47
+ email: jmettraux@gmail.com
48
+ executables: []
49
+
50
+ extensions: []
51
+
52
+ extra_rdoc_files:
53
+ - LICENSE.txt
54
+ - README.rdoc
55
+ files:
56
+ - CHANGELOG.txt
57
+ - LICENSE.txt
58
+ - README.rdoc
59
+ - Rakefile
60
+ - TODO.txt
61
+ - examples/equation.rb
62
+ - examples/state_machine.rb
63
+ - lib/volute.rb
64
+ - spec/include_volute_spec.rb
65
+ - spec/spec_helper.rb
66
+ - spec/volute_guard_spec.rb
67
+ - spec/volute_spec.rb
68
+ - volute.gemspec
69
+ has_rdoc: true
70
+ homepage: http://github.com/jmettraux/volute/
71
+ licenses: []
72
+
73
+ post_install_message:
74
+ rdoc_options:
75
+ - --charset=UTF-8
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: "0"
83
+ version:
84
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: "0"
89
+ version:
90
+ requirements: []
91
+
92
+ rubyforge_project: rufus
93
+ rubygems_version: 1.3.5
94
+ signing_key:
95
+ specification_version: 3
96
+ summary: placing some [business] logic outside of classes
97
+ test_files:
98
+ - spec/include_volute_spec.rb
99
+ - spec/spec_helper.rb
100
+ - spec/volute_guard_spec.rb
101
+ - spec/volute_spec.rb
102
+ - examples/equation.rb
103
+ - examples/state_machine.rb