我有一个模型(比如说Car
),其中一个方法需要访问current_user来确定是否允许用户执行该方法所做的事情。
例如,方法可能希望执行以下操作:
我需要将此业务逻辑放在模型中,不在控制器中,这样它就是一个地方我的业务逻辑将会。可以从控制器以外的位置调用该方法。
我知道有像cancan,declarative_authorization等宝石,但它们似乎对我需要做的事情有些过分。而且,访问模型中的current_user不被视为“正确的方法”。
然后,我如何在模型中进行检查,但仍感觉“干净”?
答案 0 :(得分:1)
我遇到过“current_user”需要与模型紧密连接的情况,但是我在Controller中处理了它并且它运行良好。以下是一些例子:
我的模特是“照片”。照片由用户拥有,人们与照片互动的方式显然与他们是否拥有照片密切相关。
在show动作中,我需要加载用户为照片添加的现有评级(以便他们可以编辑它)或允许他们创建一个新评级:
def show
@photo = Photo.find(params[:id])
if user_signed_in?
if @rating = current_user.ratings.find_by_photo_id(params[:id])
@rating
@current_user_rating = @rating.value
else
@rating = current_user.ratings.new
@current_user_rating = "n/a"
end
end
end
当人们创建照片时,我希望将它们自动分配给当前用户。
def new
@photo = Photo.new
end
def create
@photo = current_user.photos.create(params[:photo])
if @photo.save
redirect_to user_path(current_user), :notice => t('photo.notice.created')
else
render 'new'
end
end
只有照片的所有者才能更改它们:
def edit
@photo = Photo.find(params[:id])
if @photo.user == current_user
render 'edit'
else
redirect_to user_path(current_user), :alert => t('application.error.unauthorized')
end
end
def update
@photo = current_user.photos.find_by_id(params[:id])
@photo.update_attributes(params[:photo])
if @photo.save
redirect_to user_path(current_user), :notice => t('photo.notice.updated')
else
render 'edit'
end
end
这种方法基于“current_user”对象与会话绑定的约束,只有控制器才知道。所以,简而言之,我还没有找到一种将“current_user”集成到模型中的好方法,但我已经能够找到(我认为)将模型和控制器联系在一起的非常干净的方法,以便可以提供由控制器。
对于大多数问题,一个相当简单的解决方案,如果您的控制器开始变得混乱,将采用一大块逻辑并在模型中定义为方法,但需要一个参数=一个用户对象。然后,您可以从控制器向该方法提供“current_user”,模型将处理其余部分。
祝你好运!此外,如果其他人对此有任何更好的想法,我很乐意听到他们!答案 1 :(得分:0)
在控制器中处理身份验证。
示例:将auth逻辑放在父ApplicationController中。
class ApplicationController < ActionController::Base
protect_from_forgery
protected
# Returns the currently logged in user or nil if there isn't one
def current_user
return unless session[:user_id]
@current_user ||= User.find_by_id(session[:user_id])
end
# Make current_user available in templates as a helper
helper_method :current_user
# Filter method to enforce a login requirement
# Apply as a before_filter on any controller you want to protect
def authenticate
logged_in? ? true : access_denied
end
# Predicate method to test for a logged in user
def logged_in?
current_user.is_a? User
end
# Make logged_in? available in templates as a helper
helper_method :logged_in?
def access_denied
redirect_to login_path, :notice => "Please log in to continue" and return false
end
end
现在current_user是登录用户的访问者,您可以在任何控制器中访问它,您可以在对模型执行任何操作之前在适当的控制器中执行授权逻辑。
你的权利。模型不关心授权或访问它们的人。