11

The title pretty much explains it. I'm having an odd situation where views that allow users to delete notifications using Ajax cause the current_user to be logged out. I don't even know where to begin debugging this...

Here's the controller

class NotificationsController < ApplicationController

    def destroy
        @notification = Notification.find(params[:id])
        @notification.destroy
        respond_to do |format|
            format.js
        end
    end


end

This is the entire controller, nothing is abridged. The notifications are generated by the system, so the only action a user can take is to "dismiss" (ie. delete) them.

I also tried this using the newer respond_with syntax and had the same effect.

I'm using Devise, and Rails 3.0.9. Any idea what could be going on -- or suggestions on how to debug??

-- EDIT 1 --

Routes.rb

resources :notifications, :only => [:destroy]

Delete link

%span.delete= link_to( 'dismiss', notification_path(notification), :method => :delete, :remote => true )

-- EDIT 2 --

Well, I noticed something new in the logs -- see **** below.

Started DELETE "/notifications/10" for 127.0.0.1 at 2011-06-21 21:47:15 -0500
  Processing by NotificationsController#destroy as JS
  Parameters: {"id"=>"10"}
  SQL (0.4ms)   SELECT name
 FROM sqlite_master
 WHERE type = 'table' AND NOT name = 'sqlite_sequence'
  SQL (0.3ms)   SELECT name
 FROM sqlite_master
 WHERE type = 'table' AND NOT name = 'sqlite_sequence'

  User Load (0.7ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
  Slug Load (0.4ms)  SELECT "slugs".* FROM "slugs" WHERE ("slugs".sluggable_id = 1 AND "slugs".sluggable_type = 'User') ORDER BY id DESC LIMIT 1
  ****AREL (0.3ms)  UPDATE "users" SET "remember_token" = NULL, "remember_created_at" = NULL, "updated_at" = '2011-06-22 02:47:15.913839', "preferences" = '---
:email_notifications: ''true''
' WHERE "users"."id" = 1
  Notification Load (0.2ms)  SELECT "notifications".* FROM "notifications" WHERE "notifications"."id" = 10 LIMIT 1
  User Load (1.0ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
  AREL (0.3ms)  UPDATE "users" SET "notifications_count" = COALESCE("notifications_count", 0) - 1 WHERE "users"."id" = 1
  AREL (0.1ms)  DELETE FROM "notifications" WHERE "notifications"."id" = 10
Rendered notifications/destroy.js.erb (0.7ms)
Completed 200 OK in 6416ms (Views: 9.6ms | ActiveRecord: 4.1ms)

So, there it is, it looks like part of the users table is getting set to null, particularly the remember_token which I suspect is triggering Devise to end the session, or maybe this is done by Devise after the session is destroyed. But how do I track that down?

The only thing I can think of that causes notifications to interact with Users is there's a counter_cache on Users for notifications_count.

I appreciate thoughts and suggestions on how to debug!

-- EDIT 3 --

After digging with ruby-debug it looks like the issue is related to Devise and changes to the rails.js script. See:

https://github.com/plataformatec/devise/issues/913

https://github.com/ryanb/cancan/issues/280

I'm trying out some of the suggestions on those threads and will post if I find a solution.

0

4 Answers 4

12

I had a similar problem. Solution was as simple as adding

<%= csrf_meta_tag %>

to the layout.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks AlphaOne. In my case csrf_meta_tag was already in the layout, but this is indeed what the bug is related to. Older versions of jQuery UJS weren't sending the csrf token and new versions of devise required it for all ajax requests.
Thanks, I was experiencing this error with a recent app on Rails 3.2.2 and the latest devise, and this was the culprit.
For me, it was <%= csrf_meta_tags %>, i.e. an s on the end.
9

It turns out this had to do with changes to the Rails jQuery UJS driver and Devise. I had updated Devise without updating jQuery UJS -- and Devise was expecting the CSRF token to be handled differently, so it was processing the ajax request as unauthorized which meant destroying the current user's session. Upgrading to the latest jQuery Rails driver fixed the problem.

4 Comments

Which driver and version are you using? I have that same problem (driving me nuts!), and it's not fixed with jquery-ujs v. 1.0.12. Also running Devise 1.3.4 Thanks!
@Chris, using devise (1.4.0), and jquery-rails (1.0.12)
@Chris: I found that using the debugger helped, it made me realize that Devise was processing the request as unauthorized. Check the rails guide (guides.rubyonrails.org/debugging_rails_applications.html). The key thing you're looking for is your Ajax request needs to be sending the CSRF token or else Devise will log you out.
Thanks much Andrew. I figured it out. My problem was that I had forgotten to include a call to the csrf_meta_tag helper in my layout's head. Ugh! Now it works with devise 1.3.4 and jquery-rails 1.0.12.
0

Are you sure this controller and action are the ones that are triggered by the request? It sounds like the path you are DELETEing isnt right and you are hitting your sessions path instead.

1 Comment

I just tested this using non-ajax link and setting the controller to format.html { redirect_to :back }. This works as expected and doesn't destroy the session.
0

Is it possible that the destroy notification path is redirecting to the session destroy path through JS?

Do you have destroy.js template in your notifications views? try adding one that is empty see if you get a different result.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.