17

I'm creating a rails app that includes devise. I'm trying to add Twilio messaging to my site with Ngrok, i used this tutorial: https://www.twilio.com/blog/2016/04/receive-and-reply-to-sms-in-rails.html

I was able to open Ngrok in the console and get the web-id they give for my url. I keep getting this error when I plug the url into my browser ..I'm supposed to get to my own rails local app. Not sure whats wrong.

What I added in my messaging controller made for ngrok:

class MessagesController < ApplicationController
  skip_before_filter :verify_authenticity_token 
  skip_before_filter :authenticate_user!, :only => "reply"

def reply
   message_body = params["Body"]
   from_number = params["From"]
   boot_twilio
   sms = @client.messages.create(
     from: Rails.application.secrets.twilio_number,
     to: from_number,
     body: "Hello there, thanks for texting me. Your number is #{from_number}."
  )
  #twilio expects a HTTP response to this request
end


private
 def boot_twilio
   account_sid = Rails.application.secrets.twilio_sid
   auth_token = Rails.application.secrets.twilio_token
   @client = Twilio::REST::Client.new account_sid, auth_token
 end
end

really unsure what is wrong. when its not connecting to the 'def reply' and authenticate_user should be defined by devise.

Promise Preston
  • 24,334
  • 12
  • 145
  • 143
DianaBG
  • 1,511
  • 3
  • 10
  • 13
  • What error do you mean? Is there a stack trace? – philnash Dec 21 '16 at 15:32
  • The error is "ArgumentError in MessagesController#reply" "Before process_action callback :authenticate_user! has not been defined" – DianaBG Dec 21 '16 at 15:38
  • and it highlights the line "skip_before_filter :authenticate_user!, :only => "reply"" – DianaBG Dec 21 '16 at 15:38
  • When I remove that line, i get this error: " NameError in MessagesController#reply" ..." uninitialized constant MessagesController::Twilio". this highlights the code ``` @client = Twilio::REST::Client.new account_sid, auth_token``` – DianaBG Dec 21 '16 at 15:40
  • OK, still looking into your first error, but that second one sounds like you haven't installed the Twilio gem. Add `gem 'twilio-ruby'` to your Gemfile, run `bundle install` and try that again. – philnash Dec 21 '16 at 15:41
  • Are you using Rails 4 or 5? – philnash Dec 21 '16 at 15:42

2 Answers2

30

Twilio developer evangelist here.

It looks like this was a problem that Rails 5 seems to have introduced. If the filter hasn't been defined by the time it is used in a controller it will raise an error. This was discovered in the Clearance project too.

Their fix was to pass the raise: false option to skip_before_filter:

class MessagesController < ApplicationController
  skip_before_filter :verify_authenticity_token 
  skip_before_filter :authenticate_user!, :only => "reply", :raise => false

end
philnash
  • 70,667
  • 10
  • 60
  • 88
6

I had a similar issue to this when I was working on a Rails 6 application with Devise gem for authentication and authorization.

I added a skip_before_action :authenticate_admin!, only: [:index, :show] to the Products controller

class ProductsController < ApplicationController
  before_action :set_product, only: [:show, :edit, :update, :destroy]
  skip_before_action :authenticate_admin!, only: [:index, :show]

  def index
    @products = Product.all
  end
  .
  .
  .
end

And it was throwing the error below when I visit the Products page:

Before process_action callback :authenticate_admin! has not been defined

Here's how I fixed it:

To use the skip_before_action :authenticate_admin!, only: [:index, :show] in the Products controller, I first needed to define the before_action :authenticate_user! in the application_controller:

# app/controllers/application_controller.rb:

class ApplicationController < ActionController::Base

  protect_from_forgery with: :exception

  before_action :authenticate_admin!

end

Now I can use the skip_before_action :authenticate_admin!, only: [:index, :show] in the Products controller:

class ProductsController < ApplicationController
  before_action :set_product, only: [:show, :edit, :update, :destroy]
  skip_before_action :authenticate_admin!, only: [:index, :show]

  def index
    @products = Product.all
  end
  .
  .
  .
end

An alternative, if I don't want to define the before_action :authenticate_user! in the application_controller is to use the before_action :authenticate_admin!, except: [:index, :show]:

class ProductsController < ApplicationController
  before_action :set_product, only: [:show, :edit, :update, :destroy]
  before_action :authenticate_admin!, except: [:index, :show]

  def index
    @products = Product.all
  end
  .
  .
  .
end

That's all.

I hope this helps

Promise Preston
  • 24,334
  • 12
  • 145
  • 143
  • 1
    This should be the correct answer. It makes the whole sense after reading this. Because authenticate_admin is a devise method, it's not a callback out of the box. – Federico Martinez Jun 21 '23 at 22:50