1

Традиционные методы управления рельсами направлены на сокращение логического кода в контроллерах, поскольку они спроектированы для маршрутизации и выполнения сложных задач.Rails 4: можно ли извлечь сложную логику аутентификации из контроллера?

Однако, если у вас есть полукомплексная логика аутентификации, как вы можете разумно извлечь эту логику из контроллера?

Следующее представляется мне довольно «стандартной» логикой для любого базового приложения. Хотя логика напрямую связана с «маршрутизацией», кажется, что я ввожу логику в контроллер, и она не очень маленькая ... Я собираюсь перехитрить здесь?

Можно ли легко извлечь эту логику в отдельный класс, поскольку метод redirect_to ... доступен только в контроллерах?

class SessionsController < ApplicationController 
    # Login page POSTs here to perform authentication logic 
    def create 
    user = User.find_by(email: params[:email]) 
    if user and user.authenticate(params[:password]) # default has_secure_password 
     if user.confirmed? 
     if user.account.active? 
      flash[:notice] = "Successfully logged in" 
      redirect_to root_path 
     else 
      flash[:error] = "This account is no longer active" 
      redirect_to inactive_account_path(user.account) 
     end 
     else 
     flash[:alert] = "You are not confirmed yet" 
     redirect_to confirmation_path(user.confirmation_token) 
     end 
    else 
     flash[:error] = "Invalid email or password" 
     redirect_to login_path 
    end 
    end 
end 

ответ

1

Вы можете бросить все эти вещи в функцию обратного вызова или подобные, если вам нравится, так что этот метод немного проще, но маршрутизация должна более или менее относится к контроллеру.

class SessionsController < ApplicationController 
    before_filter :set_user, :check_confirmed 

    def create 
    if user.account.active? 
     flash[:notice] = 'Successfully logged in' 
     redirect_to root_path 
    else 
     flash[:error] = 'This account is no longer active' 
     redirect_to inactive_account_path(user.account) 
    end 
    end 

    private 

    def set_user 
    user = User.find_by(email: params[:email]) 
    return if user.authenticate(params[:password]) 
    flash[:error] = 'Invalid email or password' 
    redirect_to login_path 
    end 

    def check_confirmed 
    return if user.confirmed? 
    flash[:alert] = 'You are not confirmed yet' 
    redirect_to confirmation_path(user.confirmation_token) 
    end 
end 

Обратите внимание, что вы можете поставить обратные вызовы в ApplicationController, если вы хотите, чтобы ваш SessionsController сам немного компактнее.

НО Помните, что это сессии контроллер и состояние пользователя следует управлять в другом месте. В идеале, с логической позиции, ваш метод создания должен выглядеть следующим образом:

def create 
    user = User.find_by(email: params[:email]) 
    if user 
    flash[:notice] = 'Successfully logged in' 
    redirect_to root_path 
    else 
    flash[:error] = 'Invalid email or password' 
    redirect_to login_path 
    end 
end 

И поставил обратные вызовы статуса пользователя или аналогичные в другом месте (ApplicationController или whatevs).