adhearsion 2.0.0.rc4 → 2.0.0.rc5

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.
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