volute 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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