Проблемы с обратными вызовами Warden::Manager after_authentication

Это, вероятно, было бы проще для меня, если бы Ruby был моим первым языком, но в любом случае, вот мой вопрос:

Используя Rails 3.1, я пытаюсь получить доступ к некоторым обратным вызовам Warden Manager с помощью Devise, чтобы создавать новую «Корзину» каждый раз, когда пользователь входит в систему. Я помещаю эту логику в свой ApplicationController. Проблема в том, что когда я создаю корзину, я хочу присвоить ей идентификатор пользователя. Я пытался использовать вспомогательный метод Devise current_user, но это не работает.

Самое главное, я хочу знать, почему я не могу получить доступ к своим вспомогательным методам или методам, определенным в ApplicationController, из блока Warden::Manager. Но я также хочу знать, как я могу отредактировать свой код, чтобы я мог использовать метод Devise's current_user (и мой метод current_cart, показанный ниже) внутри блока без ошибок, подобных той, что указана ниже.

Вот мой код:

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

Вот ошибка:

NameError in Devise::SessionsController#create

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

person varatis    schedule 13.01.2012    source источник


Ответы (2)


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

В блоке after_authentication у вас нет доступа к файлу current_user. Вместо этого используйте только что прошедший проверку подлинности пользовательский объект, переданный в качестве параметра.

person Steven Zeiler    schedule 08.02.2012

Ну, я не очень люблю отвечать на свои вопросы, но, поскольку я чувствую себя обязанным не оставлять ни одного вопроса без ответа:

То, что я в конечном итоге сделал, было, по сути, полным обходом всего обратного вызова. Хотя это может быть идиосинкразическим для моей ситуации, вот что я сделал:

В контроллере приложения:

before_filter :authenticate_user!, :only => :current_cart

Таким образом, для вызова current_cart пользователь должен войти в систему. А также измените current_cart на:

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

Таким образом, current_cart создает новую корзину, если она еще не существует. Вы также можете выполнять действия before_filter в других контроллерах, которые могут повлиять на вашу корзину, таких как LineItems или Products.

person varatis    schedule 13.01.2012
comment
Вам не нужно выполнять Cart.find в случае, когда session[:cart_id] равен нулю, потому что у вас уже есть тележка. На один запрос БД меньше. - person Robin; 09.04.2012