adzap-voice_form 0.1.1 → 0.2.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/History.txt +3 -0
- data/README.markdown +75 -6
- data/Rakefile +2 -2
- data/examples/my_component.rb +10 -9
- data/lib/voice_form.rb +0 -8
- data/lib/voice_form/form.rb +2 -15
- data/lib/voice_form/form_field.rb +2 -1
- data/lib/voice_form/form_methods.rb +8 -8
- data/spec/form_field_spec.rb +1 -3
- data/spec/form_spec.rb +3 -3
- metadata +6 -4
data/History.txt
CHANGED
data/README.markdown
CHANGED
@@ -33,7 +33,6 @@ command to play your sound files.
|
|
33
33
|
|
34
34
|
class MyComponent
|
35
35
|
include VoiceForm
|
36
|
-
add_call_context :as => :call_context
|
37
36
|
|
38
37
|
voice_form do
|
39
38
|
|
@@ -53,6 +52,10 @@ command to play your sound files.
|
|
53
52
|
@age.to_i <= @max_age
|
54
53
|
end
|
55
54
|
|
55
|
+
confirm(:accept => 1, :reject => 2, :timeout => 3, :attempts => 3) do
|
56
|
+
"You entered #{@age}. Press 1 to continue or 2 to try again."
|
57
|
+
end
|
58
|
+
|
56
59
|
invalid do
|
57
60
|
call_context.speak "Your age must be less than #{@max_age}. Try again."
|
58
61
|
end
|
@@ -72,8 +75,7 @@ command to play your sound files.
|
|
72
75
|
In your dialplan:
|
73
76
|
|
74
77
|
general {
|
75
|
-
|
76
|
-
my_component.start_voice_form
|
78
|
+
MyComponent.new.start_voice_form(self)
|
77
79
|
}
|
78
80
|
|
79
81
|
That covers most of the functionality, and hopefully it makes sense pretty much straight
|
@@ -82,11 +84,14 @@ away.
|
|
82
84
|
You don't have to start the form from the dialplan, but it makes it simple. You could start it from
|
83
85
|
within a component method.
|
84
86
|
|
85
|
-
All blocks (setup, validate,
|
86
|
-
component methods and instance variables in them and they will work.
|
87
|
+
All callback blocks (setup, validate, timeout etc.) are evaluated in the component scope so you can use
|
88
|
+
component methods and instance variables in them and they will work. You don't have to define any
|
89
|
+
callbacks if the field is straight forward and only depends on its length.
|
87
90
|
|
88
91
|
For a more complete example see the examples folder.
|
89
92
|
|
93
|
+
## Commands
|
94
|
+
|
90
95
|
### voice_form
|
91
96
|
|
92
97
|
The flow of the form works like a stack. So each field and do_block are executed in order until the
|
@@ -137,8 +142,72 @@ There can only be one `prompt` but you can have multiple `reprompt`s. When you a
|
|
137
142
|
what the prompt is if there is input the first time or the input is invalid.
|
138
143
|
|
139
144
|
|
140
|
-
|
145
|
+
### Callbacks
|
146
|
+
|
147
|
+
The available callbacks that can be defined for a field are as follows
|
148
|
+
|
149
|
+
- setup
|
150
|
+
- timeout
|
151
|
+
- validate
|
152
|
+
- invalid
|
153
|
+
- confirm
|
154
|
+
- success
|
155
|
+
- failure
|
156
|
+
|
157
|
+
Each of them takes a block which is executed as a specific point in the process of getting form input.
|
158
|
+
All of them are optional. The block for a callback is evaluated in the scope of the component so any
|
159
|
+
instance variables and component methods are available to use including the call context.
|
160
|
+
|
161
|
+
The details of each callback are as follows
|
162
|
+
|
163
|
+
### setup
|
164
|
+
|
165
|
+
This is run once only for a field if defined before any prompts
|
166
|
+
|
167
|
+
### timeout
|
168
|
+
|
169
|
+
This is run if no input is received.
|
170
|
+
|
171
|
+
### validate
|
172
|
+
|
173
|
+
This is run after input of a valid length. The validate block is where you put validation logic of the
|
174
|
+
value just input by the user. The block should return `true` if the value is valid or `false` otherwise.
|
175
|
+
If the validate callback returns false then the invalid callback will be called next.
|
176
|
+
|
177
|
+
### invalid
|
178
|
+
|
179
|
+
The invalid callback is called if the input value is not of a valid length or the validate block returns
|
180
|
+
false.
|
181
|
+
|
182
|
+
### confirm
|
183
|
+
|
184
|
+
The confirm callback is called after the input has been validated. The confirm callback is a little different
|
185
|
+
from the others. Idea is that you return either an array or string of the audio files or TTS text, respectively,
|
186
|
+
you want to play as the prompt for confirming the value entered. The confirm block also takes a few options:
|
187
|
+
|
188
|
+
- :accept - the number to press to accept the field value entered. Default is 1.
|
189
|
+
- :reject - the number to press the reject the field value entered and try again. Default is 2.
|
190
|
+
- :attempts - the number of attempts to try to get a confirmation response. Default is 3
|
191
|
+
- :timeout - the number of seconds to wait for input after the confirmation response. Default is 3.
|
192
|
+
|
193
|
+
The value returned from the block should form the complete list of audio files or TTS text to prompt the user
|
194
|
+
including the values to accept of reject the value.
|
195
|
+
|
196
|
+
For example, in a field called my_field:
|
197
|
+
|
198
|
+
confirm(:accept => 1, :reject => 2, :attempts => 3) do
|
199
|
+
['you-entered', @my_field.scan(/\d/), 'is-this-correct', 'press-1-accept-2-try-again'].flatten
|
200
|
+
end
|
201
|
+
|
202
|
+
The above will `play` the array of audo files as the prompt for confirmation.
|
203
|
+
|
204
|
+
confirm(:accept => 1, :reject => 2, :attempts => 3) do
|
205
|
+
"You entered #{@my_field}. Is this correct? Press 1 to accept or 2 try again."
|
206
|
+
end
|
207
|
+
|
208
|
+
The above will `speak` the string as the prompt for confirmation.
|
141
209
|
|
210
|
+
If no valid input is entered for the confirmation
|
142
211
|
|
143
212
|
TODO: More docs
|
144
213
|
|
data/Rakefile
CHANGED
@@ -5,11 +5,11 @@ require 'date'
|
|
5
5
|
require 'spec/rake/spectask'
|
6
6
|
|
7
7
|
GEM = "voice_form"
|
8
|
-
GEM_VERSION = "0.
|
8
|
+
GEM_VERSION = "0.2.0"
|
9
9
|
AUTHOR = "Adam Meehan"
|
10
10
|
EMAIL = "adam.meehan@gmail.com"
|
11
11
|
HOMEPAGE = "http://github.com/adzap/voice_form"
|
12
|
-
SUMMARY = "A
|
12
|
+
SUMMARY = "A plugin for Adhearsion to create forms in the style of the VoiceXML form element."
|
13
13
|
|
14
14
|
spec = Gem::Specification.new do |s|
|
15
15
|
s.name = GEM
|
data/examples/my_component.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
class MyComponent
|
2
2
|
include VoiceForm
|
3
|
-
|
3
|
+
|
4
|
+
delegate :play, :speak, :to => :call_context
|
4
5
|
|
5
6
|
voice_form do
|
6
7
|
field(:age, :max_length => 3, :attempts => 3) do
|
@@ -12,20 +13,20 @@ class MyComponent
|
|
12
13
|
validate { @age.to_i < @max_age }
|
13
14
|
|
14
15
|
invalid do
|
15
|
-
|
16
|
+
speak "Your age must be less than #{@max_age}. Try again."
|
16
17
|
end
|
17
18
|
|
18
19
|
success do
|
19
|
-
|
20
|
+
speak "You are #{@age} years old."
|
20
21
|
end
|
21
22
|
|
22
23
|
failure do
|
23
|
-
|
24
|
+
speak "You could not enter your age. Thats a bad sign."
|
24
25
|
end
|
25
26
|
end
|
26
27
|
|
27
28
|
do_block do
|
28
|
-
|
29
|
+
speak "Get ready for the next question."
|
29
30
|
end
|
30
31
|
|
31
32
|
field(:postcode, :length => 4, :attempts => 5) do
|
@@ -35,19 +36,19 @@ class MyComponent
|
|
35
36
|
|
36
37
|
invalid do
|
37
38
|
if @postcode.size < 4
|
38
|
-
|
39
|
+
speak "Your postcode must 4 digits."
|
39
40
|
else
|
40
|
-
|
41
|
+
speak "Your postcode cannot start with a 0."
|
41
42
|
end
|
42
43
|
end
|
43
44
|
|
44
45
|
success do
|
45
|
-
|
46
|
+
speak "Your postcode is #{@postcode.scan(/\d/).join(', ')}."
|
46
47
|
end
|
47
48
|
|
48
49
|
failure do
|
49
50
|
if @age.empty?
|
50
|
-
|
51
|
+
speak "Lets start over shall we."
|
51
52
|
form.restart
|
52
53
|
end
|
53
54
|
end
|
data/lib/voice_form.rb
CHANGED
@@ -1,11 +1,3 @@
|
|
1
1
|
require 'voice_form/form_methods'
|
2
2
|
require 'voice_form/form'
|
3
3
|
require 'voice_form/form_field'
|
4
|
-
|
5
|
-
Adhearsion::Components::Behavior.module_eval do
|
6
|
-
include VoiceForm::FormMethods
|
7
|
-
end
|
8
|
-
|
9
|
-
Adhearsion::Components::Behavior::ClassMethods.module_eval do
|
10
|
-
include VoiceForm::MacroMethods
|
11
|
-
end
|
data/lib/voice_form/form.rb
CHANGED
@@ -6,22 +6,18 @@ module VoiceForm
|
|
6
6
|
attr_accessor :form_stack
|
7
7
|
attr_reader :current_field
|
8
8
|
|
9
|
-
def initialize(options={})
|
9
|
+
def initialize(options={}, &block)
|
10
10
|
@options = options
|
11
|
-
|
12
11
|
@form_stack = []
|
13
12
|
@stack_index = 0
|
13
|
+
self.instance_eval(&block)
|
14
14
|
end
|
15
15
|
|
16
16
|
def run(component)
|
17
17
|
@component = component
|
18
18
|
|
19
|
-
alias_call_context
|
20
|
-
|
21
19
|
add_field_accessors
|
22
|
-
|
23
20
|
run_setup
|
24
|
-
|
25
21
|
run_form_stack
|
26
22
|
end
|
27
23
|
|
@@ -92,15 +88,6 @@ module VoiceForm
|
|
92
88
|
slot.is_a?(VoiceForm::FormField)
|
93
89
|
end
|
94
90
|
|
95
|
-
def alias_call_context
|
96
|
-
# hack to avoid setting the call_context in each field for different context name
|
97
|
-
if context_name = @options[:call_context] && !@component.respond_to?(:call_context)
|
98
|
-
@component.class_eval do
|
99
|
-
alias_method :call_context, context_name
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
91
|
end
|
105
92
|
|
106
93
|
end
|
@@ -4,11 +4,12 @@ module VoiceForm
|
|
4
4
|
attr_reader :name
|
5
5
|
attr_accessor :prompts
|
6
6
|
|
7
|
-
def initialize(name, options, component)
|
7
|
+
def initialize(name, options, component, &block)
|
8
8
|
@name, @options, @component = name, options, component
|
9
9
|
@options.reverse_merge!(:attempts => 5, :call_context => 'call_context')
|
10
10
|
@callbacks = {}
|
11
11
|
@prompts = []
|
12
|
+
self.instance_eval(&block)
|
12
13
|
end
|
13
14
|
|
14
15
|
def prompt(options)
|
@@ -16,7 +16,7 @@ module VoiceForm
|
|
16
16
|
include InstanceMethods
|
17
17
|
|
18
18
|
cattr_accessor :voice_form_options
|
19
|
-
attr_accessor :form
|
19
|
+
attr_accessor :form, :call_context
|
20
20
|
end
|
21
21
|
|
22
22
|
self.voice_form_options = [options, block]
|
@@ -26,10 +26,11 @@ module VoiceForm
|
|
26
26
|
|
27
27
|
module InstanceMethods
|
28
28
|
|
29
|
-
def start_voice_form
|
29
|
+
def start_voice_form(call)
|
30
30
|
raise "No voice form defined" unless self.voice_form_options
|
31
|
-
|
32
|
-
|
31
|
+
options, block = *self.class.voice_form_options
|
32
|
+
@call_context = call
|
33
|
+
self.form = VoiceForm::Form.new(options, &block)
|
33
34
|
self.form.run(self)
|
34
35
|
end
|
35
36
|
|
@@ -39,12 +40,11 @@ module VoiceForm
|
|
39
40
|
|
40
41
|
# Can be used in a form or stand-alone in a component method
|
41
42
|
def field(field_name, options={}, &block)
|
42
|
-
raise
|
43
|
+
raise "A field requires a block" unless block_given?
|
43
44
|
|
44
|
-
form_field = VoiceForm::FormField.new(field_name, options, self)
|
45
|
+
form_field = VoiceForm::FormField.new(field_name, options, self, &block)
|
45
46
|
|
46
|
-
form_field.
|
47
|
-
raise 'At least one prompt is required' if form_field.prompts.empty?
|
47
|
+
raise 'A field requires a prompt to be defined' if form_field.prompts.empty?
|
48
48
|
|
49
49
|
if self.class == VoiceForm::Form
|
50
50
|
self.form_stack << form_field
|
data/spec/form_field_spec.rb
CHANGED
@@ -267,9 +267,7 @@ describe VoiceForm::FormField do
|
|
267
267
|
|
268
268
|
def form_field(field, options={}, &block)
|
269
269
|
self.class.class_eval { attr_accessor field }
|
270
|
-
item = VoiceForm::FormField.new(field, {:attempts => 3}.merge(options), self )
|
271
|
-
|
272
|
-
item.instance_eval(&block)
|
270
|
+
item = VoiceForm::FormField.new(field, {:attempts => 3}.merge(options), self, &block)
|
273
271
|
item
|
274
272
|
end
|
275
273
|
end
|
data/spec/form_spec.rb
CHANGED
@@ -16,7 +16,7 @@ describe VoiceForm::Form do
|
|
16
16
|
|
17
17
|
self.class.voice_form &call_me
|
18
18
|
|
19
|
-
start_voice_form
|
19
|
+
start_voice_form(@call_context)
|
20
20
|
end
|
21
21
|
|
22
22
|
it "should call setup block" do
|
@@ -203,8 +203,8 @@ describe VoiceForm::Form do
|
|
203
203
|
|
204
204
|
def new_voice_form
|
205
205
|
self.class.voice_form { }
|
206
|
-
|
207
|
-
self.form.
|
206
|
+
options, block = *self.class.voice_form_options
|
207
|
+
self.form = VoiceForm::Form.new(options, &block)
|
208
208
|
end
|
209
209
|
|
210
210
|
def run_form
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: adzap-voice_form
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Meehan
|
@@ -9,11 +9,11 @@ autorequire: voice_form
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2009-01-16 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
16
|
-
description: A
|
16
|
+
description: A plugin for Adhearsion to create forms in the style of the VoiceXML form element.
|
17
17
|
email: adam.meehan@gmail.com
|
18
18
|
executables: []
|
19
19
|
|
@@ -27,10 +27,12 @@ files:
|
|
27
27
|
- Rakefile
|
28
28
|
- lib/voice_form.rb
|
29
29
|
- lib/voice_form
|
30
|
+
- lib/voice_form/simple_menu.rb
|
30
31
|
- lib/voice_form/form.rb
|
31
32
|
- lib/voice_form/form_field.rb
|
32
33
|
- lib/voice_form/form_methods.rb
|
33
34
|
- spec/form_field_spec.rb
|
35
|
+
- spec/simple_menu_spec.rb
|
34
36
|
- spec/spec_helper.rb
|
35
37
|
- spec/form_spec.rb
|
36
38
|
- examples/my_component.rb
|
@@ -60,6 +62,6 @@ rubyforge_project:
|
|
60
62
|
rubygems_version: 1.2.0
|
61
63
|
signing_key:
|
62
64
|
specification_version: 2
|
63
|
-
summary: A
|
65
|
+
summary: A plugin for Adhearsion to create forms in the style of the VoiceXML form element.
|
64
66
|
test_files: []
|
65
67
|
|