Problems with Warden::Manager after_authentication callbacks

2.4k views Asked by At

This would probably be simpler for me if Ruby was my first language, but anyway, here's my question:

Using Rails 3.1, I'm trying to access some of the Warden Manager callbacks with Devise to create a new 'Cart' each time a user signs in. I'm placing this logic in my ApplicationController. Problem is, when I create a Cart, I want to give it a user id. I've been trying to use Devise's helper method current_user but that isn't working.

Most importantly, I want to know why I can't access my helper methods or methods defined in the ApplicationController from within the Warden::Manager block. But I also want to know how I can edit my code so I can use Devise's current_user method (and my current_cart method, shown below) within the block without errors like the one listed below being called.

Here's my code:

class ApplicationController < ActionController::Base
  helper :all
  helper_method :current_user
  protect_from_forgery

  before_filter :fetch_categories

  .
  .
  .

  def current_cart
    @current_cart ||= Cart.find_by_user_id(current_user.id)
  end

  Warden::Manager.after_authentication do |user, auth, opts|
    Cart.create!(:user_id => current_user.id)
  end
end

Here's the error:

NameError in Devise::SessionsController#create

undefined local variable or method `current_user' for ApplicationController:Class
2

There are 2 answers

1
varatis On BEST ANSWER

Well, I don't really like answering my own questions, but since I feel obligated to leave no question unanswered:

What I ended up doing was essentially side-stepping the whole callback thing altogether. Although this might be idiosyncratic to my situation, here's what I did:

In the application controller:

before_filter :authenticate_user!, :only => :current_cart

That way, a user must be signed in for current_cart to be called. And also change current_cart to:

def current_cart
  session[:cart_id] ||= Cart.create(:user_id => current_user.id).id
  @current_cart ||= Cart.find(session[:cart_id])
end

So current_cart instantiates a new cart if it doesn't yet exist. You can also do the before_filter stuff in other controllers which might affect your cart, such as LineItems or Products.

0
Steven Zeiler On
Warden::Manager.after_authentication do |user, auth, opts|
  Cart.create!(:user_id => user.id)
end

In the after_authentication block you don't have access to the current_user. Instead, use the newly-authenticated user object passed as a parameter.