twilio 1.4.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.
Files changed (45) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +24 -0
  3. data/Rakefile +49 -0
  4. data/VERSION.yml +4 -0
  5. data/lib/twilio.rb +42 -0
  6. data/lib/twilio/account.rb +12 -0
  7. data/lib/twilio/call.rb +34 -0
  8. data/lib/twilio/connection.rb +17 -0
  9. data/lib/twilio/incoming_phone_number.rb +13 -0
  10. data/lib/twilio/local_phone_number.rb +18 -0
  11. data/lib/twilio/notification.rb +17 -0
  12. data/lib/twilio/outgoing_caller_id.rb +29 -0
  13. data/lib/twilio/recording.rb +21 -0
  14. data/lib/twilio/toll_free_phone_number.rb +18 -0
  15. data/lib/twilio/twilio_object.rb +11 -0
  16. data/lib/twilio/verb.rb +186 -0
  17. data/test/fixtures/xml/account.xml +11 -0
  18. data/test/fixtures/xml/account_renamed.xml +11 -0
  19. data/test/fixtures/xml/call.xml +18 -0
  20. data/test/fixtures/xml/call_new.xml +14 -0
  21. data/test/fixtures/xml/calls.xml +36 -0
  22. data/test/fixtures/xml/incoming_phone_number.xml +12 -0
  23. data/test/fixtures/xml/incoming_phone_numbers.xml +24 -0
  24. data/test/fixtures/xml/notification.xml +19 -0
  25. data/test/fixtures/xml/notifications.xml +32 -0
  26. data/test/fixtures/xml/outgoing_caller_id.xml +10 -0
  27. data/test/fixtures/xml/outgoing_caller_id_new.xml +7 -0
  28. data/test/fixtures/xml/outgoing_caller_ids.xml +20 -0
  29. data/test/fixtures/xml/recording.xml +10 -0
  30. data/test/fixtures/xml/recordings.xml +20 -0
  31. data/test/fixtures/xml/transcription.xml +13 -0
  32. data/test/fixtures/xml/transcriptions.xml +26 -0
  33. data/test/fixtures/yml/verb_responses.yml +89 -0
  34. data/test/test_helper.rb +29 -0
  35. data/test/twilio/account_test.rb +23 -0
  36. data/test/twilio/call_test.rb +59 -0
  37. data/test/twilio/connection_test.rb +15 -0
  38. data/test/twilio/incoming_phone_number_test.rb +22 -0
  39. data/test/twilio/local_phone_number_test.rb +23 -0
  40. data/test/twilio/notification_test.rb +28 -0
  41. data/test/twilio/outgoing_caller_id_test.rb +42 -0
  42. data/test/twilio/recording_test.rb +42 -0
  43. data/test/twilio/toll_free_phone_number_test.rb +23 -0
  44. data/test/twilio/verb_test.rb +126 -0
  45. metadata +126 -0
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Phil Misiowiec, Webficient LLC
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,24 @@
1
+ = twilio
2
+
3
+ This wrapper defines each of the interfaces currently supported by Twilio REST API.
4
+
5
+ Sample Usage:
6
+
7
+ First create a connection object:
8
+
9
+ c = Twilio::Connection.new('my_twilio_sid', 'my_auth_token')
10
+
11
+ Now instantiate other objects by passing in the connection:
12
+
13
+ a = Twilio::Account.new(c)
14
+ a.update_name('sparky')
15
+
16
+ call = Twilio::Call.new(c)
17
+ call.make('1234567890', '9876543210', 'http://mysite.com/connected_call')
18
+
19
+ recording = Twilio::Recording.new(c)
20
+ recording.list
21
+
22
+ == Copyright
23
+
24
+ Copyright (c) 2009 Phil Misiowiec, Webficient LLC. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,49 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "twilio"
8
+ gem.summary = %Q{Twilio API Client}
9
+ gem.email = "github@webficient.com"
10
+ gem.homepage = "http://github.com/webficient/twilio"
11
+ gem.authors = ["Phil Misiowiec"]
12
+ gem.add_dependency 'builder'
13
+ gem.add_dependency 'httparty'
14
+ end
15
+ rescue LoadError
16
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
17
+ end
18
+
19
+ require 'rake/rdoctask'
20
+ Rake::RDocTask.new do |rdoc|
21
+ rdoc.rdoc_dir = 'rdoc'
22
+ rdoc.title = 'twilio'
23
+ rdoc.options << '--line-numbers' << '--inline-source'
24
+ rdoc.rdoc_files.include('README*')
25
+ rdoc.rdoc_files.include('lib/**/*.rb')
26
+ end
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.pattern = 'test/**/*_test.rb'
32
+ test.verbose = false
33
+ end
34
+
35
+ begin
36
+ require 'rcov/rcovtask'
37
+ Rcov::RcovTask.new do |test|
38
+ test.libs << 'test'
39
+ test.pattern = 'test/**/*_test.rb'
40
+ test.verbose = true
41
+ end
42
+ rescue LoadError
43
+ task :rcov do
44
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
45
+ end
46
+ end
47
+
48
+
49
+ task :default => :test
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :minor: 4
3
+ :patch: 0
4
+ :major: 1
data/lib/twilio.rb ADDED
@@ -0,0 +1,42 @@
1
+ $:.unshift(File.dirname(__FILE__))
2
+
3
+ #--
4
+ # Copyright (c) 2009 Phil Misiowiec, phil@webficient.com
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining
7
+ # a copy of this software and associated documentation files (the
8
+ # "Software"), to deal in the Software without restriction, including
9
+ # without limitation the rights to use, copy, modify, merge, publish,
10
+ # distribute, sublicense, and/or sell copies of the Software, and to
11
+ # permit persons to whom the Software is furnished to do so, subject to
12
+ # the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be
15
+ # included in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+ #++
25
+
26
+ require 'rubygems'
27
+ gem 'httparty', '>= 0.4.3'
28
+ require 'httparty'
29
+ gem 'builder', '>= 2.1.2'
30
+ require 'builder'
31
+
32
+ require 'twilio/twilio_object'
33
+ require 'twilio/account'
34
+ require 'twilio/call'
35
+ require 'twilio/connection'
36
+ require 'twilio/incoming_phone_number'
37
+ require 'twilio/local_phone_number'
38
+ require 'twilio/notification'
39
+ require 'twilio/outgoing_caller_id'
40
+ require 'twilio/recording'
41
+ require 'twilio/toll_free_phone_number'
42
+ require 'twilio/verb'
@@ -0,0 +1,12 @@
1
+ module Twilio
2
+ # The Account resource represents your Twilio Account.
3
+ class Account < TwilioObject
4
+ def get
5
+ self.connection.class.get('')
6
+ end
7
+
8
+ def update_name(name)
9
+ self.connection.class.put('', :body => {:FriendlyName => name})
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,34 @@
1
+ module Twilio
2
+ # A Call represenents a connection between a telephone and Twilio. This may be
3
+ # inbound, when a person calls your application, or outbound when your application
4
+ # initiates the call, either via the REST API, or during a call via the Dial Verb.
5
+ class Call < TwilioObject
6
+ # Example:
7
+ # c = Twilio::Connection.new('my_twilio_sid', 'my_auth_token')
8
+ # call = Twilio::Call.new(c)
9
+ # response = call.make(CALLER_ID, user_number, 'http://myapp.com/twilio_response_handler')
10
+ def make(caller, called, url, optional = {})
11
+ self.connection.class.post("/Calls", :body => {:Caller => caller, :Called => called, :Url => url}.merge(optional))
12
+ end
13
+
14
+ def list(optional = {})
15
+ self.connection.class.get("/Calls", :query => optional)
16
+ end
17
+
18
+ def get(call_sid)
19
+ self.connection.class.get("/Calls/#{call_sid}")
20
+ end
21
+
22
+ def segments(call_sid, call_segment_sid = nil)
23
+ self.connection.class.get("/Calls/#{call_sid}/Segments#{ '/' + call_segment_sid if call_segment_sid }")
24
+ end
25
+
26
+ def recordings(call_sid)
27
+ self.connection.class.get("/Calls/#{call_sid}/Recordings")
28
+ end
29
+
30
+ def notifications(call_sid)
31
+ self.connection.class.get("/Calls/#{call_sid}/Notifications")
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,17 @@
1
+ module Twilio
2
+ # The Connection class caches the Twilio API base path and authentication credentials.
3
+ # It is passed into the constructor of other TwilioObject's, avoiding the need to
4
+ # explicitly set credentials with each API call.
5
+ #
6
+ # Example:
7
+ # c = Twilio::Connection.new('my_twilio_sid', 'my_auth_token')
8
+ class Connection
9
+ include HTTParty
10
+ TWILIO_URL = "https://api.twilio.com/2008-08-01/Accounts"
11
+
12
+ def initialize(account_sid, auth_token)
13
+ self.class.base_uri "#{TWILIO_URL}/#{account_sid}"
14
+ self.class.basic_auth account_sid, auth_token
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,13 @@
1
+ module Twilio
2
+ # An IncomingPhoneNumber resource represents a phone number given to you by
3
+ # Twilio to receive incoming phone calls.
4
+ class IncomingPhoneNumber < TwilioObject
5
+ def list(optional = {})
6
+ self.connection.class.get("/IncomingPhoneNumbers", :query => optional)
7
+ end
8
+
9
+ def get(incoming_sid)
10
+ self.connection.class.get("/IncomingPhoneNumbers/#{incoming_sid}")
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,18 @@
1
+ module Twilio
2
+ # This sub-resource represents only Local phone numbers, or in other words, not toll-free numbers.
3
+ # Also allows you to request a new local phone number be added to your account.
4
+ class LocalPhoneNumber < TwilioObject
5
+ def create(url, area_code = nil, method = 'POST', friendly_name = nil)
6
+ self.connection.class.post("/IncomingPhoneNumbers/Local", :body => {
7
+ :Url => url,
8
+ :AreaCode => area_code,
9
+ :Method => method,
10
+ :FriendlyName => friendly_name
11
+ })
12
+ end
13
+
14
+ def list
15
+ self.connection.class.get("/IncomingPhoneNumbers/Local")
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,17 @@
1
+ module Twilio
2
+ # A Notification represenents a log entry made by Twilio in the course of handling
3
+ # your calls or using the REST API.
4
+ class Notification < TwilioObject
5
+ def list(optional = {})
6
+ self.connection.class.get('/Notifications', :query => optional)
7
+ end
8
+
9
+ def get(notification_sid)
10
+ self.connection.class.get("/Notifications/#{notification_sid}")
11
+ end
12
+
13
+ def delete(notification_sid)
14
+ self.connection.class.delete("/Notifications/#{notification_sid}")
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,29 @@
1
+ module Twilio
2
+ # An OutgoingCallerId resource represents an outgoing Caller ID that you have
3
+ # registered with Twilio for use when making an outgoing call or using the Dial Verb.
4
+ class OutgoingCallerId < TwilioObject
5
+ def create(phone_number, friendly_name = phone_number, call_delay = 0)
6
+ self.connection.class.post("/OutgoingCallerIds", :body => {
7
+ :PhoneNumber => phone_number,
8
+ :FriendlyName => friendly_name,
9
+ :CallDelay => call_delay
10
+ })
11
+ end
12
+
13
+ def list(optional = {})
14
+ self.connection.class.get("/OutgoingCallerIds", :query => optional)
15
+ end
16
+
17
+ def get(callerid_sid)
18
+ self.connection.class.get("/OutgoingCallerIds/#{callerid_sid}")
19
+ end
20
+
21
+ def update_name(callerid_sid, name)
22
+ self.connection.class.put("/OutgoingCallerIds/#{callerid_sid}", :body => {:FriendlyName => name})
23
+ end
24
+
25
+ def delete(callerid_sid)
26
+ self.connection.class.delete("/OutgoingCallerIds/#{callerid_sid}")
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,21 @@
1
+ module Twilio
2
+ # Recordings are generated when you use the Record Verb. Those recordings are
3
+ # hosted on Twilio's REST API for you to access.
4
+ class Recording < TwilioObject
5
+ def list(optional = {})
6
+ self.connection.class.get("/Recordings", :query => optional)
7
+ end
8
+
9
+ def get(recording_sid)
10
+ self.connection.class.get("/Recordings/#{recording_sid}")
11
+ end
12
+
13
+ def delete(recording_sid)
14
+ self.connection.class.delete("/Recordings/#{recording_sid}")
15
+ end
16
+
17
+ def transcriptions(recording_sid, transcription_sid = nil)
18
+ self.connection.class.get("/Recordings/#{recording_sid}/Transcriptions#{ '/' + transcription_sid if transcription_sid }")
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,18 @@
1
+ module Twilio
2
+ # This sub-resource represents only Toll Free phone numbers, or in other words, not local numbers.
3
+ # Also allows you to request a new toll free phone number be added to your account.
4
+ class TollFreePhoneNumber < TwilioObject
5
+ def create(url, area_code = nil, method = 'POST', friendly_name = nil)
6
+ self.connection.class.post("/IncomingPhoneNumbers/TollFree", :body => {
7
+ :Url => url,
8
+ :AreaCode => area_code,
9
+ :Method => method,
10
+ :FriendlyName => friendly_name
11
+ })
12
+ end
13
+
14
+ def list
15
+ self.connection.class.get("/IncomingPhoneNumbers/TollFree")
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,11 @@
1
+ module Twilio
2
+ class TwilioObject #:nodoc: all
3
+ include HTTParty
4
+
5
+ attr_reader :connection
6
+
7
+ def initialize(connection)
8
+ @connection = connection
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,186 @@
1
+ module Twilio
2
+ # Twilio Verbs enable your application to respond to Twilio requests (to your app) with XML responses.
3
+ #
4
+ # In addition to the 5 verbs supported by Twilio (say, play, gather, record, dial),
5
+ # this class also implements dynamic interfaces that allow you to combine useful
6
+ # operations into a single call. See below methods for examples.
7
+ class Verb
8
+ class << self
9
+ # The Say verb converts text to speech that is read back to the caller.
10
+ # Say is useful for dynamic text that is difficult to prerecord.
11
+ #
12
+ # Examples:
13
+ # Twilio::Verb.say('The time is 9:35 PM.')
14
+ # Twilio::Verb.say_3_times('The time is 9:35 PM.')
15
+ #
16
+ # With numbers, 12345 will be spoken as "twelve thousand three hundred forty five" while
17
+ # 1 2 3 4 5 will be spoken as "one two three four five."
18
+ #
19
+ # Twilio::Verb.say_4_times('Your PIN is 1234')
20
+ # Twilio::Verb.say_4_times('Your PIN is 1 2 3 4')
21
+ #
22
+ # If you need a longer pause between each loop, use the pause form:
23
+ #
24
+ # Twilio::Verb.say_4_times_with_pause('Your PIN is 1 2 3 4')
25
+ #
26
+ # Options (see http://www.twilio.com/docs/api_reference/TwiML/say) are passed in as a hash:
27
+ #
28
+ # Twilio::Verb.say('The time is 9:35 PM.', :voice => 'woman')
29
+ # Twilio::Verb.say('The time is 9:35 PM.', {:voice => 'woman', :language => 'es'})
30
+ def say(*args, &block)
31
+ options = {:voice => 'man', :language => 'en', :loop => 1}
32
+ args.each do |arg|
33
+ case arg
34
+ when String
35
+ options[:text_to_speak] = arg
36
+ when Hash
37
+ options.merge!(arg)
38
+ else
39
+ raise ArgumentError, 'say expects String or Hash argument'
40
+ end
41
+ end
42
+
43
+ xml = Builder::XmlMarkup.new
44
+ xml.instruct!
45
+ xml.Response {
46
+ if options[:pause]
47
+ loop_with_pause(options[:loop], xml) do
48
+ xml.Say(options[:text_to_speak], :voice => options[:voice], :language => options[:language])
49
+ end
50
+ else
51
+ xml.Say(options[:text_to_speak], :voice => options[:voice], :language => options[:language], :loop => options[:loop])
52
+ end
53
+ }
54
+ end
55
+
56
+ # The Play verb plays an audio URL back to the caller.
57
+ # Examples:
58
+ # Twilio::Verb.play('http://foo.com/cowbell.mp3')
59
+ # Twilio::Verb.play_3_times('http://foo.com/cowbell.mp3')
60
+ #
61
+ # If you need a longer pause between each loop, use the pause form:
62
+ #
63
+ # Twilio::Verb.play_3_times_with_pause('http://foo.com/cowbell.mp3')
64
+ #
65
+ # Options (see http://www.twilio.com/docs/api_reference/TwiML/play) are passed in as a hash,
66
+ # however, since the Play verb only supports 'loop' as the current option, you can instead use the
67
+ # above form to keep things concise.
68
+ def play(*args, &block)
69
+ options = {:loop => 1}
70
+ args.each do |arg|
71
+ case arg
72
+ when String
73
+ options[:audio_url] = arg
74
+ when Hash
75
+ options.merge!(arg)
76
+ else
77
+ raise ArgumentError, 'play expects String or Hash argument'
78
+ end
79
+ end
80
+
81
+ xml = Builder::XmlMarkup.new
82
+ xml.instruct!
83
+ xml.Response {
84
+ if options[:pause]
85
+ loop_with_pause(options[:loop], xml) do
86
+ xml.Play(options[:audio_url])
87
+ end
88
+ else
89
+ xml.Play(options[:audio_url], :loop => options[:loop])
90
+ end
91
+ }
92
+ end
93
+
94
+ # The Gather verb collects digits entered by a caller into their telephone keypad.
95
+ # When the caller is done entering data, Twilio submits that data to a provided URL,
96
+ # as either a HTTP GET or POST request, just like a web browser submits data from an HTML form.
97
+ #
98
+ # Options (see http://www.twilio.com/docs/api_reference/TwiML/gather) are passed in as a hash
99
+ #
100
+ # Examples:
101
+ # Twilio::Verb.gather
102
+ # Twilio::Verb.gather(:action => 'http://foobar.com')
103
+ # Twilio::Verb.gather(:finishOnKey => '*')
104
+ # Twilio::Verb.gather(:action => 'http://foobar.com', :finishOnKey => '*')
105
+ def gather(*args, &block)
106
+ options = args.shift
107
+ xml = Builder::XmlMarkup.new
108
+ xml.instruct!
109
+ xml.Response { xml.Gather(options) }
110
+ end
111
+
112
+ # The Record verb records the caller's voice and returns a URL that links to a file
113
+ # containing the audio recording.
114
+ #
115
+ # Options (see http://www.twilio.com/docs/api_reference/TwiML/record) are passed in as a hash
116
+ #
117
+ # Examples:
118
+ # Twilio::Verb.record
119
+ # Twilio::Verb.record(:action => 'http://foobar.com')
120
+ # Twilio::Verb.record(:finishOnKey => '*')
121
+ # Twilio::Verb.record(:transcribe => true, :transcribeCallback => '/handle_transcribe')
122
+ def record(*args, &block)
123
+ options = args.shift
124
+ xml = Builder::XmlMarkup.new
125
+ xml.instruct!
126
+ xml.Response { xml.Record(options) }
127
+ end
128
+
129
+ # The Dial verb connects the current caller to an another phone. If the called party picks up,
130
+ # the two parties are connected and can communicate until one hangs up. If the called party does
131
+ # not pick up, if a busy signal is received, or the number doesn't exist, the dial verb will finish.
132
+ #
133
+ # If an action verb is provided, Twilio will submit the outcome of the call attempt to the action URL.
134
+ # If no action is provided, Dial will fall through to the next verb in the document.
135
+ #
136
+ # Note: this is different than the behavior of Record and Gather. Dial does not submit back to the
137
+ # current document URL if no action is provided.
138
+ #
139
+ # Options (see http://www.twilio.com/docs/api_reference/TwiML/dial) are passed in as a hash
140
+ #
141
+ # Examples:
142
+ # Twilio::Verb.dial('415-123-4567')
143
+ # Twilio::Verb.dial('415-123-4567', :action => 'http://foobar.com')
144
+ # Twilio::Verb.dial('415-123-4567', {:timeout => 10, :callerId => '858-987-6543'})
145
+ def dial(*args, &block)
146
+ number_to_dial = ''
147
+ options = {}
148
+ args.each do |arg|
149
+ case arg
150
+ when String
151
+ number_to_dial = arg
152
+ when Hash
153
+ options.merge!(arg)
154
+ else
155
+ raise ArgumentError, 'dial expects String or Hash argument'
156
+ end
157
+ end
158
+
159
+ xml = Builder::XmlMarkup.new
160
+ xml.instruct!
161
+ xml.Response { xml.Dial(number_to_dial, options) }
162
+ end
163
+
164
+ def method_missing(method_id, *args) #:nodoc:
165
+ if match = /(say|play|gather|record|dial)(_(\d+)_)times(_with_pause$*)/.match(method_id.to_s)
166
+ verb = match.captures.first
167
+ how_many_times = match.captures[1]
168
+ pause = match.captures[2] == '_with_pause'
169
+ self.send(verb, args.first, { :loop => Integer(how_many_times), :pause => pause})
170
+ else
171
+ raise NoMethodError.new("Method --- #{method_id} --- not found")
172
+ end
173
+ end
174
+
175
+ private
176
+
177
+ def loop_with_pause(loop_count, xml, &verb_action)
178
+ last_iteration = loop_count-1
179
+ loop_count.times do |i|
180
+ yield verb_action
181
+ xml.Pause unless i == last_iteration
182
+ end
183
+ end
184
+ end
185
+ end
186
+ end