ruby on the phone
TRANSCRIPT
![Page 1: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/1.jpg)
RUBY ON THE PHONEMat Schaffer, Ruby Nation 2011
![Page 2: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/2.jpg)
MAT SCHAFFER
github.com/matschaffer
@matschaffer
![Page 3: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/3.jpg)
RAILS – JAVASCRIPT(for hire)
![Page 4: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/4.jpg)
CALLME
![Page 5: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/5.jpg)
•Provider comparison
•Making phone calls
•Handling Call flow
•SMS
•Testing
![Page 6: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/6.jpg)
JSON REST API
they host a JVM script
IM and Twitter integration
3¢ per minute
$3 per month per line
XML REST API
you generate TwiML
just phone and SMS
1¢/2¢ per minute
$1 per month per line
![Page 7: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/7.jpg)
PLACING CALLS
![Page 8: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/8.jpg)
https://github.com/webficient/twilio
require 'rubygems'require 'twilio'
Twilio.connect(ENV['TWILIO_SID'], ENV['TWILIO_TOKEN'])Twilio::Call.make('+12155551213', '+12155551234', 'http://myapp.com')
From*
ToWhat do to
![Page 9: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/9.jpg)
> curl -d From=+12155551212 \ -d To=+12155551234 \ -d Url=http://myapp.com \ -u $TWILIO_SID:$TWILIO_TOKEN \https://api.twilio.com/2010-04-01/Accounts/$TWILIO_SID/Calls
![Page 10: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/10.jpg)
POST https://twilio/callUrl=http://me/calls
POST https://me/callsCallSid=CAc7ca63fb9...
![Page 11: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/11.jpg)
<?xml version="1.0" encoding="UTF-8" ?><Response> <Say>Hello Ruby Nation</Say></Response>
![Page 12: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/12.jpg)
INCOMING CALLS
![Page 13: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/13.jpg)
![Page 14: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/14.jpg)
require 'rubygems'require 'twilio'
Twilio.connect(ENV['TWILIO_SID'], ENV['TWILIO_TOKEN'])resp = Twilio::AvailablePhoneNumbers.search_local(:postal_code => '20191')numbers = resp['TwilioResponse']['AvailablePhoneNumbers']['AvailablePhoneNumber']
my_number = numbers.firstTwilio::IncomingPhoneNumber.create(:PhoneNumber => my_number['PhoneNumber'], :VoiceUrl => 'http://myapp.com')
![Page 15: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/15.jpg)
![Page 16: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/16.jpg)
<?xml version="1.0" encoding="UTF-8"?><Response> <Say>Welcome to the party!</Say> <Dial> <Conference>rubynation_partyline</Conference> </Dial></Response>
For a good time call (540) 318-2266
post '/' do return Twilio::Verb.new do |v| v.say "Welcome to the party!" v.dial do v.conference 'rubynation_partyline' end end.responseend
![Page 17: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/17.jpg)
![Page 18: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/18.jpg)
TWIML
![Page 19: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/19.jpg)
VERBS
OUTPUT <Play> <Say>
INPUT <Gather> <Record>
CALLS <Dial><Number> <Conference>
<Dial><Number> <Conference>
OTHERS <Hangup> <Reject> <Pause> <Redirect> <Sms>
![Page 20: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/20.jpg)
WHOOPS! RAILS ISSUES
• skip_before_filter :verify_authenticity_token
• be careful about response types (use *.xml or filter)
• tough to fit in RESTful model
![Page 21: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/21.jpg)
CALL FLOW
![Page 22: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/22.jpg)
TWILIO LOOP
1.Post initial call information with new CallSid
2.Perform action
3.Post action’s result with original CallSid
4.Repeat
![Page 23: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/23.jpg)
<?xml version="1.0" encoding="UTF-8"?><Response> <Gather action="/calls/response.xml"> "<Say>Hi there, press a number</Say> </Gather></Response>
<?xml version="1.0" encoding="UTF-8"?><Response> <Say>Thanks for your input</Say></Response>
![Page 24: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/24.jpg)
<?xml version="1.0" encoding="UTF-8"?><Response> <Dial action="/calls/complete.xml"> " <Number url="/calls/prompt.xml?connection_id=1">2155551212</Number> </Dial></Response>
<?xml version="1.0" encoding="UTF-8"?><Response> <Say> Here’s what the called person hears </Say></Response>
<?xml version="1.0" encoding="UTF-8"?><Response> <Say>The caller hears this after the call</Say></Response>
![Page 25: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/25.jpg)
SMS
![Page 26: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/26.jpg)
require 'rubygems'require 'twilio'
Twilio.connect(ENV['TWILIO_SID'], ENV['TWILIO_TOKEN'])Twilio::Sms.message('+12155551213', '+12155551234', "Hello sms")
SENDING
![Page 27: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/27.jpg)
RECEIVINGrequire 'rubygems'require 'sinatra'require 'twilio'
post '/sms' do return Twilio::Verb.new do |v| v.sms "Ohai #{params[:From]}" end.responseend
<?xml version="1.0" encoding="UTF-8"?><Response> <Sms>Ohai +12155551212</Sms></Response>
![Page 28: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/28.jpg)
TESTING
![Page 29: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/29.jpg)
REST CALL TESTING
• Mocking: Mocha, Rspec, etc
• HTTP Mocking: VCR, Artiface, FakeWeb, WebMock
![Page 30: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/30.jpg)
Artifice.activate_with(FakeTwilio)
require 'rubygems'require 'sinatra'
class FakeTwilio < Sinatra::Base def fixture(resource) resource.gsub!('/', '-') Rails.root.join('test', 'support', 'twilio_responses', "#{resource}-GET.xml").read end
get '/2010-04-01/Accounts/:sid/*' do |sid, resource| fixture(resource) end
post '/2010-04-01/Accounts/:sid/*' do |sid, resource| fixture(resource) endend
![Page 31: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/31.jpg)
ARTIFICE + CUCUMBER
module Selenium Net = ::Net.dup module Net HTTP = Artifice::NET_HTTP endend
class Capybara::Server Net = ::Net.dup module Net HTTP = Artifice::NET_HTTP endend
Kinda sucked. got better?
![Page 32: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/32.jpg)
TWIML TESTING
test "new should omit connected connections" do @connection.connect! post :new, :CallSid => @sid assert_match "Number", response.body assert_not_match @connection.number, response.body end
Basic match testing
![Page 33: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/33.jpg)
NEED MORE INPUT?
![Page 34: Ruby on the Phone](https://reader034.vdocuments.mx/reader034/viewer/2022052506/557cf1a0d8b42a57118b45ab/html5/thumbnails/34.jpg)
THANK YOUquestions?