adhearsion 2.0.0.rc4 → 2.0.0.rc5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/CHANGELOG.md +4 -0
  2. data/adhearsion.gemspec +1 -1
  3. data/bin/ahn +0 -3
  4. data/lib/adhearsion.rb +7 -4
  5. data/lib/adhearsion/call.rb +1 -1
  6. data/lib/adhearsion/call_controller.rb +1 -0
  7. data/lib/adhearsion/call_controller/menu_dsl.rb +19 -0
  8. data/lib/adhearsion/call_controller/menu_dsl/calculated_match.rb +43 -0
  9. data/lib/adhearsion/call_controller/menu_dsl/calculated_match_collection.rb +45 -0
  10. data/lib/adhearsion/call_controller/menu_dsl/fixnum_match_calculator.rb +22 -0
  11. data/lib/adhearsion/call_controller/menu_dsl/match_calculator.rb +40 -0
  12. data/lib/adhearsion/call_controller/menu_dsl/menu.rb +203 -0
  13. data/lib/adhearsion/call_controller/menu_dsl/menu_builder.rb +84 -0
  14. data/lib/adhearsion/call_controller/menu_dsl/range_match_calculator.rb +60 -0
  15. data/lib/adhearsion/call_controller/menu_dsl/string_match_calculator.rb +25 -0
  16. data/lib/adhearsion/cli.rb +0 -1
  17. data/lib/adhearsion/router/route.rb +2 -2
  18. data/lib/adhearsion/version.rb +1 -1
  19. data/spec/adhearsion/call_controller/input_spec.rb +1 -1
  20. data/spec/adhearsion/call_controller/menu_dsl/calculated_match_collection_spec.rb +60 -0
  21. data/spec/adhearsion/call_controller/menu_dsl/calculated_match_spec.rb +61 -0
  22. data/spec/adhearsion/call_controller/menu_dsl/fixnum_match_calculator_spec.rb +37 -0
  23. data/spec/adhearsion/call_controller/menu_dsl/match_calculator_spec.rb +17 -0
  24. data/spec/adhearsion/call_controller/menu_dsl/menu_builder_spec.rb +151 -0
  25. data/spec/adhearsion/call_controller/menu_dsl/menu_spec.rb +373 -0
  26. data/spec/adhearsion/call_controller/menu_dsl/range_match_calculator_spec.rb +32 -0
  27. data/spec/adhearsion/call_controller/menu_dsl/string_match_calculator_spec.rb +40 -0
  28. metadata +91 -91
  29. data/lib/adhearsion/menu_dsl.rb +0 -17
  30. data/lib/adhearsion/menu_dsl/calculated_match.rb +0 -41
  31. data/lib/adhearsion/menu_dsl/calculated_match_collection.rb +0 -43
  32. data/lib/adhearsion/menu_dsl/fixnum_match_calculator.rb +0 -20
  33. data/lib/adhearsion/menu_dsl/match_calculator.rb +0 -38
  34. data/lib/adhearsion/menu_dsl/menu.rb +0 -201
  35. data/lib/adhearsion/menu_dsl/menu_builder.rb +0 -82
  36. data/lib/adhearsion/menu_dsl/range_match_calculator.rb +0 -58
  37. data/lib/adhearsion/menu_dsl/string_match_calculator.rb +0 -23
  38. data/spec/adhearsion/menu_dsl/calculated_match_collection_spec.rb +0 -58
  39. data/spec/adhearsion/menu_dsl/calculated_match_spec.rb +0 -59
  40. data/spec/adhearsion/menu_dsl/fixnum_match_calculator_spec.rb +0 -35
  41. data/spec/adhearsion/menu_dsl/match_calculator_spec.rb +0 -15
  42. data/spec/adhearsion/menu_dsl/menu_builder_spec.rb +0 -149
  43. data/spec/adhearsion/menu_dsl/menu_spec.rb +0 -371
  44. data/spec/adhearsion/menu_dsl/range_match_calculator_spec.rb +0 -30
  45. data/spec/adhearsion/menu_dsl/string_match_calculator_spec.rb +0 -38
@@ -1,5 +1,9 @@
1
1
  # [develop](https://github.com/adhearsion/adhearsion)
2
2
 
3
+ # [2.0.0.rc5](https://github.com/adhearsion/adhearsion/compare/v2.0.0.rc4...v2.0.0.rc5) - [2012-04-06](https://rubygems.org/gems/adhearsion/versions/2.0.0.rc5)
4
+ * Bugfix: Fix environment abuse in ahn CLI
5
+ * Bugfix: Celluloid log messages enter the adhearsion logger
6
+
3
7
  # [2.0.0.rc4](https://github.com/adhearsion/adhearsion/compare/v2.0.0.rc3...v2.0.0.rc4) - [2012-03-30](https://rubygems.org/gems/adhearsion/versions/2.0.0.rc4)
4
8
  * Feature: `Call#execute_controller` now takes a post-execution callback (proc)
5
9
  * Feature: App generator now includes directory scaffolding for call controller specs and a sample `spec_helper.rb` which loads app config and the `lib/` directory
@@ -40,7 +40,7 @@ Gem::Specification.new do |s|
40
40
  s.add_runtime_dependency 'girl_friday'
41
41
  s.add_runtime_dependency 'jruby-openssl' if RUBY_PLATFORM == 'java'
42
42
  s.add_runtime_dependency 'ffi', [">= 1.0.11"]
43
- s.add_runtime_dependency 'celluloid', [">= 0.9.0"]
43
+ s.add_runtime_dependency 'celluloid', [">= 0.10.0"]
44
44
  s.add_runtime_dependency 'deep_merge'
45
45
 
46
46
  # Development dependencies
data/bin/ahn CHANGED
@@ -19,9 +19,6 @@
19
19
  # with this library; if not, write to the Free Software Foundation, Inc.,
20
20
  # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
21
 
22
- $:.unshift File.expand_path(File.dirname(__FILE__) + "/../lib")
23
-
24
- require 'rubygems'
25
22
  require 'adhearsion/cli'
26
23
 
27
24
  Adhearsion::CLI::AhnCommand.start
@@ -3,8 +3,6 @@
3
3
  abort "ERROR: You are running Adhearsion on an unsupported version of Ruby (Ruby #{RUBY_VERSION} #{RUBY_RELEASE_DATE})! Please upgrade to at least Ruby v1.9.2, JRuby 1.6.5 or Rubinius 2.0." if RUBY_VERSION < "1.9.2"
4
4
 
5
5
  %w{
6
- bundler/setup
7
-
8
6
  active_support/all
9
7
  uuid
10
8
  future-resource
@@ -36,7 +34,6 @@ module Adhearsion
36
34
  autoload :Dispatcher
37
35
  autoload :Events
38
36
  autoload :Generators
39
- autoload :MenuDSL
40
37
  autoload :Initializer
41
38
  autoload :Logging
42
39
  autoload :OutboundCall
@@ -81,7 +78,7 @@ module Adhearsion
81
78
  end
82
79
 
83
80
  def active_calls
84
- if @calls && @calls.alive?
81
+ if instance_variable_defined?(:@calls) && @calls.alive?
85
82
  @calls
86
83
  else
87
84
  @calls = Calls.new
@@ -95,3 +92,9 @@ module Adhearsion
95
92
  end
96
93
 
97
94
  Celluloid.exception_handler { |e| Adhearsion::Events.trigger :exception, e }
95
+
96
+ module Celluloid
97
+ def self.logger
98
+ ::Logging.logger['Celluloid']
99
+ end
100
+ end
@@ -225,7 +225,7 @@ module Adhearsion
225
225
  end
226
226
 
227
227
  command
228
- rescue Timeout::Error => e
228
+ rescue Timeout::Error
229
229
  abort CommandTimeout.new(command.to_s)
230
230
  end
231
231
 
@@ -6,6 +6,7 @@ module Adhearsion
6
6
 
7
7
  autoload :Dial
8
8
  autoload :Input
9
+ autoload :MenuDSL
9
10
  autoload :Output
10
11
  autoload :Record
11
12
  autoload :Utility
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+
3
+ module Adhearsion
4
+ class CallController
5
+ module MenuDSL
6
+ extend ActiveSupport::Autoload
7
+
8
+ autoload :Exceptions
9
+ autoload :CalculatedMatch
10
+ autoload :CalculatedMatchCollection
11
+ autoload :MatchCalculator
12
+ autoload :FixnumMatchCalculator
13
+ autoload :RangeMatchCalculator
14
+ autoload :StringMatchCalculator
15
+ autoload :MenuBuilder
16
+ autoload :Menu
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,43 @@
1
+ # encoding: utf-8
2
+
3
+ module Adhearsion
4
+ class CallController
5
+ module MenuDSL
6
+ class CalculatedMatch
7
+
8
+ def self.failed_match!(pattern, query, match_payload)
9
+ new :pattern => pattern, :query => query, :match_payload => match_payload
10
+ end
11
+
12
+ attr_reader :match_payload, :potential_matches, :exact_matches, :pattern, :query, :block
13
+
14
+ def initialize(options = {})
15
+ @pattern, @query, @match_payload, @block = options.values_at :pattern, :query, :match_payload, :block
16
+ @potential_matches = options[:potential_matches] ? Array(options[:potential_matches]) : []
17
+ @exact_matches = options[:exact_matches] ? Array(options[:exact_matches]) : []
18
+ end
19
+
20
+ def exact_match?
21
+ exact_matches.any?
22
+ end
23
+
24
+ def potential_match?
25
+ potential_matches.any?
26
+ end
27
+
28
+ def failed_match?
29
+ !(potential_match? || exact_match?)
30
+ end
31
+
32
+ def type_of_match
33
+ if exact_match?
34
+ :exact
35
+ elsif potential_match?
36
+ :potential
37
+ end
38
+ end
39
+
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,45 @@
1
+ # encoding: utf-8
2
+
3
+ module Adhearsion
4
+ class CallController
5
+ module MenuDSL
6
+ class CalculatedMatchCollection
7
+ attr_reader :calculated_matches, :potential_matches, :exact_matches,
8
+ :actual_potential_matches, :actual_exact_matches
9
+
10
+ def initialize
11
+ @calculated_matches = []
12
+ @potential_matches = []
13
+ @exact_matches = []
14
+ @actual_potential_matches = []
15
+ @actual_exact_matches = []
16
+ end
17
+
18
+ def <<(calculated_match)
19
+ calculated_matches << calculated_match
20
+ actual_potential_matches.concat calculated_match.potential_matches
21
+ actual_exact_matches.concat calculated_match.exact_matches
22
+
23
+ potential_matches << calculated_match if calculated_match.potential_match?
24
+ exact_matches << calculated_match if calculated_match.exact_match?
25
+ end
26
+
27
+ def potential_match_count
28
+ actual_potential_matches.size
29
+ end
30
+
31
+ def exact_match_count
32
+ actual_exact_matches.size
33
+ end
34
+
35
+ def potential_match?
36
+ potential_match_count > 0
37
+ end
38
+
39
+ def exact_match?
40
+ exact_match_count > 0
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,22 @@
1
+ # encoding: utf-8
2
+
3
+ module Adhearsion
4
+ class CallController
5
+ module MenuDSL
6
+ class FixnumMatchCalculator < MatchCalculator
7
+
8
+ def match(query)
9
+ numeric_query = coerce_to_numeric query
10
+ exact_match, potential_match = nil
11
+ if pattern == numeric_query
12
+ exact_match = pattern
13
+ elsif pattern.to_s.starts_with? query.to_s
14
+ potential_match = pattern
15
+ end
16
+ new_calculated_match :query => query, :exact_matches => exact_match, :potential_matches => potential_match
17
+ end
18
+
19
+ end # class FixnumMatchCalculator
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,40 @@
1
+ # encoding: utf-8
2
+
3
+ module Adhearsion
4
+ class CallController
5
+ module MenuDSL
6
+ class MatchCalculator
7
+
8
+ class << self
9
+
10
+ def build_with_pattern(pattern, match_payload, &block)
11
+ class_for_pattern(pattern).new pattern, match_payload, &block
12
+ end
13
+
14
+ private
15
+
16
+ def class_for_pattern(pattern)
17
+ MenuDSL.const_get "#{pattern.class.name.camelize}MatchCalculator"
18
+ end
19
+ end
20
+
21
+ attr_reader :pattern, :match_payload, :block
22
+
23
+ def initialize(pattern, match_payload, &block)
24
+ @pattern, @match_payload, @block = pattern, match_payload, block
25
+ end
26
+
27
+ protected
28
+
29
+ def new_calculated_match(options)
30
+ CalculatedMatch.new({:pattern => pattern, :match_payload => match_payload, :block => block}.merge(options))
31
+ end
32
+
33
+ def coerce_to_numeric(victim)
34
+ victim.kind_of?(Numeric) ? victim : (victim.to_s =~ /^\d+$/ ? victim.to_s.to_i : nil )
35
+ end
36
+
37
+ end # class MatchCalculator
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,203 @@
1
+ # encoding: utf-8
2
+
3
+ module Adhearsion
4
+ class CallController
5
+ module MenuDSL
6
+
7
+ class Menu
8
+
9
+ DEFAULT_MAX_NUMBER_OF_TRIES = 1
10
+ DEFAULT_TIMEOUT = 5
11
+
12
+ InvalidStructureError = Class.new Adhearsion::Error
13
+
14
+ attr_reader :builder, :timeout, :tries_count, :max_number_of_tries, :terminator, :limit, :interruptible, :status
15
+
16
+ def initialize(options = {}, &block)
17
+ @tries_count = 0 # Counts the number of tries the menu's been executed
18
+ @timeout = options[:timeout] || DEFAULT_TIMEOUT
19
+ @max_number_of_tries = options[:tries] || DEFAULT_MAX_NUMBER_OF_TRIES
20
+ @terminator = options[:terminator].to_s
21
+ @limit = options[:limit]
22
+ @interruptible = options.has_key?(:interruptible) ? options[:interruptible] : true
23
+ @builder = MenuDSL::MenuBuilder.new
24
+ @terminated = false
25
+
26
+ @builder.build(&block) if block
27
+
28
+ initialize_digit_buffer
29
+ end
30
+
31
+ def validate(mode = nil)
32
+ case mode
33
+ when :basic
34
+ @terminator.present? || !!@limit || raise(InvalidStructureError, "You must specify at least one of limit or terminator")
35
+ else
36
+ @builder.has_matchers? || raise(InvalidStructureError, "You must specify one or more matchers")
37
+ end
38
+ end
39
+
40
+ def <<(other)
41
+ if other == terminator
42
+ @terminated = true
43
+ else
44
+ digit_buffer << other
45
+ end
46
+ end
47
+
48
+ def digit_buffer
49
+ @digit_buffer
50
+ end
51
+
52
+ def digit_buffer_string
53
+ digit_buffer.to_s
54
+ end
55
+ alias :result :digit_buffer_string
56
+
57
+ def digit_buffer_empty?
58
+ digit_buffer.empty?
59
+ end
60
+
61
+ def continue
62
+ return get_another_digit_or_timeout! if digit_buffer_empty?
63
+
64
+ return menu_terminated! if @terminated
65
+ return menu_limit_reached! if limit && digit_buffer.size >= limit
66
+
67
+ return menu_validator_terminated! if execute_validator_hook
68
+
69
+ calculated_matches = builder.calculate_matches_for digit_buffer_string
70
+
71
+ if calculated_matches.exact_match_count >= 1
72
+ first_exact_match = calculated_matches.exact_matches.first
73
+ if calculated_matches.potential_match_count.zero?
74
+ menu_result_found! first_exact_match, digit_buffer_string
75
+ else
76
+ get_another_digit_or_finish! first_exact_match.match_payload, first_exact_match.query
77
+ end
78
+ elsif calculated_matches.potential_match_count >= 1 || !@builder.has_matchers?
79
+ get_another_digit_or_timeout!
80
+ else
81
+ invalid!
82
+ end
83
+ end
84
+
85
+ def should_continue?
86
+ tries_count < max_number_of_tries
87
+ end
88
+
89
+ def restart!
90
+ @tries_count += 1
91
+ digit_buffer.clear!
92
+ end
93
+
94
+ def execute_invalid_hook
95
+ builder.execute_hook_for :invalid, digit_buffer_string
96
+ end
97
+
98
+ def execute_timeout_hook
99
+ builder.execute_hook_for :timeout, digit_buffer_string
100
+ end
101
+
102
+ def execute_failure_hook
103
+ builder.execute_hook_for :failure, digit_buffer_string
104
+ end
105
+
106
+ def execute_validator_hook
107
+ builder.execute_hook_for :validator, digit_buffer_string
108
+ end
109
+
110
+ protected
111
+
112
+ # If you're using a more complex class in subclasses, you may want to override this method in addition to the
113
+ # digit buffer, digit_buffer_empty, and digit_buffer_string methods
114
+ def initialize_digit_buffer
115
+ @digit_buffer = ClearableStringBuffer.new
116
+ end
117
+
118
+ def invalid!
119
+ @status = :invalid
120
+ MenuResultInvalid.new
121
+ end
122
+
123
+ def menu_result_found!(match_object, new_extension)
124
+ @status = :matched
125
+ MenuResultFound.new(match_object, new_extension)
126
+ end
127
+
128
+ def menu_terminated!
129
+ @status = :terminated
130
+ MenuTerminated.new
131
+ end
132
+
133
+ def menu_validator_terminated!
134
+ @status = :validator_terminated
135
+ MenuValidatorTerminated.new
136
+ end
137
+
138
+ def menu_limit_reached!
139
+ @status = :limited
140
+ MenuLimitReached.new
141
+ end
142
+
143
+ def get_another_digit_or_finish!(match_payload, new_extension)
144
+ @status = :multi_matched
145
+ MenuGetAnotherDigitOrFinish.new(match_payload, new_extension)
146
+ end
147
+
148
+ def get_another_digit_or_timeout!
149
+ @status = :potential
150
+ MenuGetAnotherDigitOrTimeout.new
151
+ end
152
+
153
+ # The superclass from which all message-like exceptions descend. It should never
154
+ # be instantiated directly.
155
+ MenuResult = Class.new
156
+ MenuResultDone = Class.new MenuResult
157
+
158
+ class MenuResultFound < MenuResult
159
+
160
+ attr_reader :match_object, :new_extension
161
+
162
+ def initialize(match_object, new_extension)
163
+ super()
164
+ @match_object = match_object
165
+ @new_extension = new_extension
166
+ end
167
+
168
+ end #class MenuResultFound < MenuResult
169
+
170
+ MenuGetAnotherDigit = Module.new
171
+
172
+ class MenuGetAnotherDigitOrFinish < MenuResultFound
173
+ include MenuGetAnotherDigit
174
+ end
175
+
176
+ class MenuGetAnotherDigitOrTimeout < MenuResult
177
+ include MenuGetAnotherDigit
178
+ end
179
+
180
+ MenuResultInvalid = Class.new MenuResult
181
+
182
+ MenuTerminated = Class.new MenuResultDone
183
+ MenuValidatorTerminated = Class.new MenuResultDone
184
+ MenuLimitReached = Class.new MenuResultDone
185
+
186
+ # For our default purpose, we need the digit_buffer to behave much like a normal String except that it should
187
+ # handle its own resetting (clearing)
188
+ class ClearableStringBuffer < String
189
+ def clear!
190
+ replace ""
191
+ end
192
+
193
+ def <<(other)
194
+ super other.to_s
195
+ end
196
+ end
197
+
198
+
199
+ end # class Menu
200
+
201
+ end
202
+ end
203
+ end