Question

This Twilio API Sample code isn't working in Rails 3:

#voice_controller.rb

  def reminder
    @postto = BASE_URL + '/directions'

    respond_to do |format|
      format.xml { @postto }
    end
  end

#reminder.xml.builder

xml.instruct!
xml.Response do
xml.Gather(:action => @postto, :numDigits => 1) do
    xml.Say "Hello this is a call from Twilio.  You have an appointment 
        tomorrow at 9 AM."
    xml.Say "Please press 1 to repeat this menu. Press 2 for directions.
        Or press 3 if you are done."
    end
end

Any ideas?

Twilio seems to successfully make the phone call (I can see the params with my phone number, location, etc.) but then return this vague response code:

Completed 406 Not Acceptable in 0ms
Was it helpful?

Solution

Twilio doesn't send an Accept HTTP header in its requests, which causes Rails 3 to decide that it can't respond with an appropriate content type. I think the following will get around that for you though:

# voice_controller.rb

  def reminder
    @postto = BASE_URL + '/directions'

    render :content_type => 'application/xml'
  end

OTHER TIPS

Twilio employee here. There have been a bunch of changes to Rails since this original question was posted, and I wanted to share how you might tackle this problem using Rails 4, Concerns and the Twilio Ruby gem.

In the code sample below, I define the controller in /controllers/voice_controller.rb and include a Concern called Webhookable. The Webhookable Concern lets us encapsulate logic related to Twilio webhooks (setting the HTTP response header to text/xml, rendering TwiML, validating that requests originate from Twilio, etc) into a single module.

require 'twilio-ruby'

class VoiceController < ApplicationController
  include Webhookable

  after_filter :set_header

  # controller code here

end

The Concern itself lives in /controllers/concerns/webhookable.rb and is fairly simple. Right now it simply sets the Content-Type to text/xml for all action and provides a method to render the TwiML object. I haven't included the code to validate that requests are originating from Twilio, but that would be easy to add:

module Webhookable
    extend ActiveSupport::Concern

    def set_header
      response.headers["Content-Type"] = "text/xml"
    end

    def render_twiml(response)
      render text: response.text
    end

end

Finally, here's what your reminder action might look like using the Twilio gem to generate TwiML and using the Concern to render this object as text:

  def reminder
    response = Twilio::TwiML::Response.new do |r|
      r.Gather :action => BASE_URL + '/directions', :numDigits => 1 do |g|
        g.Say 'Hello this is a call from Twilio.  You have an appointment 
    tomorrow at 9 AM.'
        g.Say 'Please press 1 to repeat this menu. Press 2 for directions.
    Or press 3 if you are done.'
      end
    end

    render_twiml response
  end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top