传统Rails最佳实践旨在减少控制器中的逻辑代码,因为它们被设计为路由而不执行复杂的任务。
但是,如果您有半复杂的身份验证逻辑,那么如何从控制器中合理地提取该逻辑呢?
在我看来,对于任何基本应用来说,这都是相当“标准”的逻辑。虽然逻辑直接与“路由”有关,但似乎我将逻辑放入控制器并且它不是很小......我在这里过度杀戮了吗?
是否可以轻松地将此逻辑提取到单独的类中,因为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
答案 0 :(得分: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
中。
但是请记住,这是会话控制器,用户状态应该在其他地方进行管理。理想情况下,从逻辑位置,您的create方法应如下所示:
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)。