How to customize ActiveRecord::RecordNotFound in Sinatra - error-handling

in my app.rb I have a get '/posts/:id' I have implemented a rescue ActiveRecord:RecordNotFound but instead of redirecting to the root url it still displays the errors. Is there a way to customize ActiveRecord errors like a custom routing error (not_found)
not_found do
slim :not_found
end
get '/posts/:id' do
begin
#post = Post.find(params[:id])
rescue ActiveRecord::RecordNotFound => e
redirect '/'#or display a view or a flash-notice
end
slim :show_post
end

The Sinatra Book recommends setting an 'error' route and defining the custom error you want to run through it. In your case, it would look something like this
error ActiveRecord::RecordNotFound do
redirect '/'
end
NOTE: You will still see the error page with the stack trace as long as your Sinatra application is set to the "Development" Environment. You can set it to other environment when you run Sinatra:
ruby app.rb -e production
More on Sinatra environments here.

Related

MIssing Devise errors when securing Login view in Rails3

I had to secure the login view (with the simple email/password form).
I'm using devise. The thing is the sign in error messages get lost somewhere (probably redirections from http to https I guess).
I tried to do the following on my application controller:
after_filter :set_devise_flash_messages, :if => :devise_controller?
def set_devise_flash_messages
if resource.errors.any?
flash[:error] = flash[:error].to_a.concat resource.errors.full_messages
flash[:error].uniq!
end
end
private :set_devise_flash_messages
but it's not working either.
Any ideas?
Thanks!!!
So, I was missing something.
I had secured the 'new' action for the devise/sessions controllers, but I wasn't securing the 'create' action. So that was causing the loss of flash messages (in between the re directions of that action's protocol).
Cheers!

Rails controller error: "No Failure App Provided" when returning 401

In my controller I want to respond to an ajax request with an http 401 (unauthorized) error if the user is not logged in. However, the code below throws a 500 internal server error instead. Rails gives the error: "No Failure App Provided".
If I use other http error codes such as :bad_request (400) it works fine. The problem seems to only be with 401 error codes. Why is this?
if signed_in?
...
else
respond_to do |format|
format.html { head :unauthorized }
end
end
This turned out to be a bug in the Monban gem I was using for authentication. It is built on top of Warden but failed to configure a "Failure App" as required by that gem.
I raised the issue, and apparently it has been resolved.
https://github.com/halogenandtoast/monban/issues/3

NoMethodError after running successful 'create' action

I am sending a post request to my API which works fine, it creates a new record. However, after the record is created i get this error in the server log
NoMethodError (undefined method `device_url' for #<Api::V1::DevicesController:0x007fa2f5dde5d8>):app/controllers/api/v1/devices_controller.rb:14:in `create'
This is my create action
def create
respond_with Device.create(params[:device])
end
All my resources are namespaced under Api#V1, here is my routes file
# Api ('/api')
namespace :api do
# Version 1 ('/api/v1')
namespace :v1 do
# Locations ('/api/v1/locations')
resources :locations
# Videos ('/api/v1/videos')
resources :videos
# Devices ('/api/v1/devices')
resources :devices
end
end
For a HTML POST request, after successfully creating the object, respond_with redirects to the object's path, i.e. here it would be equivalent to something like
redirect_to Device.create(params[:device])
which redirects to device_url. But since you have namespaced :devices in your routes, you need to specify that to your respond_with call, which would be
respond_with :api, :v1, Device.create(params[:device])

test sign up with devise

Devise 1.2 ruby on rails
I'm having difficulty testing sign up. When the user clicks sign up, they're logged in and i should see a flash message. This works but my test fails. Not sure why. How does sign up work? is there some sort of internal redirect that happens? This step fails:
Then I should see "You have registered successfully. If enabled, a confirmation was sent your e-mail."
Confirmation is not enabled in my user model.
Tehcnically, you shouldn't feel the need to unit test the devise mechanism--the gem itself is well-tested. I can understand wanting to make sure it is behaving the way you configured it though, so:
Devise definitely redirects after a successful authentication. It will set the flash message and then redirect either to what you set as the root in your routes file, or if you attempted to access a page within the site and got redirected to the login page, it will redirect you back to the page you were trying to access.
For your test, try testing that you get redirected to what you set as root in your routes.rb fil. I.e. in the devise instructions, it says to set it like
root :to => "home#index"
So, in your test try something like this:
require 'spec_helper'
describe YourController do
include Devise::TestHelpers
before (:each) do
#user = Factory.create(:user)
sign_in #user
end
describe "GET 'index'" do
it "should be successful" do
get 'index'
response.should be_success
end
it "should redirect to root" do
get 'index'
response.should redirect_to(root_url)
end
end
You can add your flash message test to this as well. Hope this helps!

Sinatra Warden with existing Ruby on Rails application that uses Devise

I am trying to split my current Ruby on Rails 3 web-application and it's web-services (API). My web-application is running on Heroku and implements API as a namespaced route within my application. For example /events returns a HTML page and /api/v1/events returns a JSON data.
According to some best practices, I want to split those into two different applications. I have chosen Sinatra to implement the API application. It works now for simple requests where authentication is not required.
My Ruby on Rails 3 application is using Devise to authenticate users. There's also ability to login with Facebook account. Now what I want to achieve, is HTTP Basic Authentication of users (including registration) through my Sinatra-based API by using Warden.
What is the best way to do that? Or maybe I can use something different then Warden?
Keep in mind that I am not very familiar with Rack :)
I was able to get it working. There were a few main aspects:
Get Devise working with Rails (Devise is a Rails app, won't work
without it)
Setup the mapping (route) on Rack level to support both Rails and Sinatra
Share the sessions between Rails and Sinatra
Setup Warden and make it available to Sinatra
Here is most relevant part of code from /config.ru:
#
# ...
# Rest with Rails
map "/" do
run MyApp::Application
end
# Anything urls starting with /slim will go to Sinatra
map "/slim" do
# make sure :key and :secret be in-sync with initializers/secret_store.rb initializers/secret_token.rb
use Rack::Session::Cookie, :key => '<< see, initializers/secret_store.rb >>', :secret => '<< copy from initializers/secret_token.rb >>'
# Point Warden to the Sinatra App
use Warden::Manager do |manager|
manager.failure_app = AppMain
manager.default_scope = Devise.default_scope
end
# Borrowed from https://gist.github.com/217362
Warden::Manager.before_failure do |env, opts|
env['REQUEST_METHOD'] = "POST"
end
run AppMain
end
See, http://labnote.beedesk.com/sinatra-warden-rails-devise for a complete solution.