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.
@@ -1,3 +1,6 @@
1
+ == 0.2.0 2009-01-16
2
+ * Updated to work with Adhearsion 0.8.0 release. Examples updated to match new usage.
3
+
1
4
  == 0.1.1 2008-11-12
2
5
  * refactored to auto include voice_form method in components, no more 'include VoiceForm'
3
6
 
@@ -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
- my_component = new_my_component
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, do_block etc.) are evaluated in the component scope so you can use
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
- TODO: Add specific info for callback and option.
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.1.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 DSL for Adhearsion to create forms in the style of the VoiceXML form element."
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
@@ -1,6 +1,7 @@
1
1
  class MyComponent
2
2
  include VoiceForm
3
- add_call_context :as => :call_context
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
- call_context.speak "Your age must be less than #{@max_age}. Try again."
16
+ speak "Your age must be less than #{@max_age}. Try again."
16
17
  end
17
18
 
18
19
  success do
19
- call_context.speak "You are #{@age} years old."
20
+ speak "You are #{@age} years old."
20
21
  end
21
22
 
22
23
  failure do
23
- call_context.speak "You could not enter your age. Thats a bad sign."
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
- call_context.speak "Get ready for the next question."
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
- call_context.speak "Your postcode must 4 digits."
39
+ speak "Your postcode must 4 digits."
39
40
  else
40
- call_context.speak "Your postcode cannot start with a 0."
41
+ speak "Your postcode cannot start with a 0."
41
42
  end
42
43
  end
43
44
 
44
45
  success do
45
- call_context.speak "Your postcode is #{@postcode.scan(/\d/).join(', ')}."
46
+ speak "Your postcode is #{@postcode.scan(/\d/).join(', ')}."
46
47
  end
47
48
 
48
49
  failure do
49
50
  if @age.empty?
50
- call_context.speak "Lets start over shall we."
51
+ speak "Lets start over shall we."
51
52
  form.restart
52
53
  end
53
54
  end
@@ -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
@@ -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
- self.form = VoiceForm::Form.new(self.class.voice_form_options[0])
32
- self.form.instance_eval(&self.class.voice_form_options[1])
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 'Field require a block' unless block_given?
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.instance_eval(&block)
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
@@ -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
@@ -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
- self.form = VoiceForm::Form.new(self.class.voice_form_options[0])
207
- self.form.instance_eval(&self.class.voice_form_options[1])
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.1.1
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: 2008-11-11 00:00:00 -08:00
12
+ date: 2009-01-16 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
16
- description: A DSL for Adhearsion to create forms in the style of the VoiceXML form element.
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 DSL for Adhearsion to create forms in the style of the VoiceXML form element.
65
+ summary: A plugin for Adhearsion to create forms in the style of the VoiceXML form element.
64
66
  test_files: []
65
67