Rails is not routing to my Twilio controller action - ruby-on-rails

I have a paid account with Twilio. In my rails app I have a very simple setup to answer an incoming phone call in rails with twilio. In routes.rb, I have
post 'communications/answer_phone' => 'communications#answer_phone'
In communications_controller.rb, I have
class CommunicationsController < ApplicationController
skip_before_action :verify_authenticity_token
def answer_phone
logger.debug '******** answered'
response = Twilio::TwiML::Response.new do |r|
r.Say "Yay! You’re on Rails!", voice: "alice"
end
render :xml => response.to_xml
end
end
If I try to call my Twilio number, ngrok says 500 Internal Server Error, so I know the request is getting to ngrok. If I look at my rails log file, I see
Started POST "/communications/answer_phone" for xxx.xxx.xxx.xxx at 2017-02-02 21:47:06 +1100
so, the request is making it to my application. I don't get ******** answered in my log file from logger.debug. The request never makes it to my answer_phone action. Any ideas what could be wrong?
UPDATE
I've done rake routes and that gives me
communications_receive_sms POST /communications/answer_phone(.:format) communications#answer_phone
That looks correct. If I deliberately spell the route incorrectly in routes.rb, I get this error
ActionController::RoutingError (No route matches [POST] "/communications/answer_phone"):
So I know the request is getting to my rails application and I know it is finding the route. What could cause rails to find the appropriate route but fail the call the associated action.

I've found a bug in rails 4.18. There is an example on the internet that makes it happen. See the link below
https://www.twilio.com/blog/2016/05/calling-rails-5-getting-started-with-twilio-on-rails.html
The example is for rails 5, so the bug must be fixed now. The following code line causes the error.
r.Say "Yay! You’re on Rails!", voice: "alice"
The apostrophe in "Yay! You’re on Rails!" is not the standard one on my computer keyboard. The normal apostrophe is hex character 0x27, the one in the word You’re is hex character 0x92. This causes a parsing error in rails. Even if I route to a different action in that controller, the error still occurs.
I hope this helps someone in the future.
EDIT
If you change the apostrophe, you'll have to restart your rails server to correct the problem

Related

Do I need to generate a controller for a Ruby on Rails Controller call?

I'm setting a session variable to a user's geographical state. I have to use a session variable because I run code on the server specific to that user on page load and I need to know where they are. This code is set up to just update the session variable.
states_controller.rb
class StatesController < ApplicationController
def loc
session[:location] = params[:location]
end
end
routes.rb
post "states/loc" => "states#loc"
The code routes properly and the session variable is updated.
However, when the process is complete I get a 500 error in the console "Missing Template" in the views directory. I haven't seen any tutorials tell users to call the command "rails generate controller" and I'm in the unique situation where I can't call this command.
What possible side effect are there to ignoring this 500 error?
*I'm running an older version of ruby and rails.
What possible side effect are there to ignoring this 500 error?
Each request is crashing your rails server. Thats not good. Since it means that some cases it may have to restart after every failed request - that eats resources like Homer Simpson at a buffet.
Your app should not be raising uncaught exceptions that cause 500 errors - thats just decent professional practice.
So how do I fix it?
Simple, if you don't want the default behavior of rendering a view tell rails to do something else:
class StatesController < ApplicationController
def loc
session[:location] = params[:location]
head :created
end
end
This sends an empty response with the 201 - CREATED http header.
See Rails Guides - Layouts and Rendering in Rails

Rails POST throws GET error

I have a rails link that's using the POST method:
link_to "Run", forecast_run_path(#forecast), method: :post
to call a defined post route:
resources :forecasts do
post :run
end
The route appears in rake routes output as expected:
forecast_run POST /forecasts/:forecast_id/run(.:format) forecasts#run
And when I inspect the page, the expected post link appears in the page:
Run Forecast
In dev it works fine, and was good in production until sometime just a few days ago - I can't find any change that seems like it should have broken it. But when I click the link, I get the error ActionController::RoutingError (No route matches [GET] "/forecasts/20/run")
I agree that no GET route matches, but it should be using POST.
This is Ruby 2.1.5, Rails 4.2.0
To my own embarrassment and for the benefit of anyone else who has the same issue:
As I switched among different clients, I didn't notice that on one of them NoScript in Firefox was blocking javascript on that site. Doh!
When you post a run, the form will direct you to the show action where it displays the newly posted run, in your case you don't have a show action for run, so implement a show action and should work fine.

How do I ignore a route in rails?

I have a route i.e. mysite.com:3000/new_route that I'd like to ignore, is this possible to do through rails and not server side?
I've read that this can be done through apache, however, my app is running on Heroku and that type of control isn't accessible to me. Therefore, I'm looking for another way to do this through Rails.
Thanks
update
I am using faye to have live notifications in my app, on localhost faye runs on port 9292 - localhost:9292/faye, all good in development mode, but in production it should point to mydomain.com/faye, there are no port numbers in production environment, and loading faye.js returns error not found
If you're talking about a resources route you don't want to be created:
resources :something, except: :new
However, I'm not exactly sure if this is what you meant by ignore.
You can define a route at the top of your routes.rb file that will redirect to some other page.
get '/new_route', redirect: '/'
By the time you ask Rails to process the route, it is already too late. If you ask rails to process a route, it will, either by returning a 404 of 500 error, or a page.
If you want the route to be processed by another application, it will need to be intercepted by your webserver (nginx or apache, or whichever one you're using). In their configuration, you just redirect that route to the other application, and every other route to the Rails app.
EDIT
Another option you have, is to forward your requests to a different server.
You add a route like
get 'faye/*query' => 'faye#get'
post 'faye/*params' => 'faye#post'
And then a controller
require 'faraday'
class FayeController < ApplicationController
APP = 'http://mydomain.com:9292'
def get
request_page :get
end
def post
request_page :post
end
private
def request_page(method)
conn = Faraday.new(:url => APP)
query = params.delete(:query)
response = conn.send method, query, params
render text: response.body.gsub(APP, 'mydomain.com/faye')
end
end
which will use Faraday to load the information from your other application.

RoR routing error in "hello world"

I'm trying to learn web-dev and decided to learn ruby on rails. I'm doing the first tutorial from "Agile Web Development with Rails". I've seen there are quite a few search results on google, but all the recommendation is "to restart the server", which does not help my case.
So, I started webrick and generate controller Say with these code:
def hello
end
and then I added hello.rhtml, which has some basic html with message "Hello from rails".
When i type in browser: http://localhost:3000/say/hello
I get : No route matches [GET] "/say/hello"
I tried to restart webrick, doesn't work. The bug-name suggest it has to do with routes, i've got two versions of the book, none of them have the steps to alter the routes.rb and within routes.rb i have commented-out stuff and class definition.
Does anyone know what should i do?
I'm guessing is a problem in your routes file. You need to define what you want rails to do (which controller+action you want to be perform) when that URL is received. So, do the following:
match 'say/hello', :to => "say#hello"
This will tell rails that when a URL with say/hello is received, the hello action of the controller say has to be performed.

rails: displaying a user friendly message for a routing error in rails

i am working in rails 2.3 on mac osx leopard.
every time i type a url that does not exist in a rails application i get the following error
Routing Error
No route matches "/whatever_i_typed" with {:method=>:get}
this is find for development, but i was wondering how i can make sure users see a friendlier 'oops! not found' page. i was thinking about doing a begin...rescue block but i didn't know where to put it, not did i know the error code (i.e ActiveRecord::RecordNotFound)
thanks!
yuval
This error will never appear in production. Instead, users will see the public/404.html page.
To try this out on your localhost, put passenger/mongrel into production mode. Override the local_request? method on your ApplicationController like so:
class ApplicationController
def local_request?
false
end
end
If you'd like to experiment with dynamic behavior you can check out the rescue_from class method on ActionController.
How about
map.connect '*url', :controller => "not_found"
as a last routes.rb entry? I think it should do the trick, shouldn't it?
I found the below url helpful for Rails 3.0.. users.
http://techoctave.com/c7/posts/36-rails-3-0-rescue-from-routing-error-solution

Resources