Allow pre-condition instances to define symbol
[gitorious:use_case.git] / lib / use_case / outcome.rb
1 # encoding: utf-8
2 # --
3 # The MIT License (MIT)
4 #
5 # Copyright (C) 2013 Gitorious AS
6 #
7 # Permission is hereby granted, free of charge, to any person obtaining a copy
8 # of this software and associated documentation files (the "Software"), to deal
9 # in the Software without restriction, including without limitation the rights
10 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 # copies of the Software, and to permit persons to whom the Software is
12 # furnished to do so, subject to the following conditions:
13 #
14 # The above copyright notice and this permission notice shall be included in all
15 # copies or substantial portions of the Software.
16 #
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 # SOFTWARE.
24 #++
25
26 module UseCase
27   class Outcome
28     def pre_condition_failed?; false; end
29     def success?; false; end
30     def success; end
31     def result; end
32     def pre_condition_failed; end
33     def failure; end
34   end
35
36   class SuccessfulOutcome < Outcome
37     def initialize(result = nil)
38       @result = result
39     end
40
41     def success?; true; end
42
43     def success
44       yield @result if block_given?
45       @result
46     end
47
48     def result; @result; end
49
50     def to_s
51       "#<UseCase::SuccessfulOutcome: #{@result}>"
52     end
53   end
54
55   class PreConditionFailed < Outcome
56     def initialize(pre_condition = nil)
57       @pre_condition = pre_condition
58       @failure = PreConditionFailure.new(@pre_condition)
59     end
60
61     def pre_condition_failed?; true; end
62
63     def pre_condition_failed
64       yield @failure if block_given?
65       @pre_condition
66     end
67
68     def to_s
69       "#<UseCase::PreConditionFailed: #{@pre_condition}>"
70     end
71   end
72
73   class PreConditionFailure
74     attr_reader :pre_condition
75     def initialize(pre_condition); @pre_condition = pre_condition; end
76
77     def when(symbol, &block)
78       raise Exception.new("Cannot call when after otherwise") if @otherwise
79       if symbol == self.symbol
80         @called = true
81         yield(@pre_condition)
82       end
83     end
84
85     def otherwise(&block)
86       @otherwise = true
87       yield(@pre_condition) if !@called
88     end
89
90     def symbol
91       return @pre_condition.symbol if @pre_condition.respond_to?(:symbol)
92       klass = @pre_condition.class
93       return klass.symbol if klass.respond_to?(:symbol)
94       klass.name.gsub(/([^A-Z])([A-Z])/, '\1_\2').gsub(/[:_]+/, "_").downcase.to_sym
95     end
96   end
97
98   class FailedOutcome < Outcome
99     attr_reader :input
100
101     def initialize(errors = nil)
102       @errors = errors
103     end
104
105     def failure
106       yield @errors if block_given?
107       @errors
108     end
109
110     def to_s
111       "#<UseCase::FailedOutcome: #{@errors}>"
112     end
113   end
114 end