before_filter :require_owner [英] before_filter :require_owner
问题描述
我有许多资源(行程、日程安排等),其操作应该仅限于资源的所有者.
I have a number of resources (Trips, Schedules, etc) with actions that should be limited to just the resource's owner.
您如何使用 ApplicationController 中定义的 #require_owner 方法来实现代码以实现此目的?理想情况下,代码将查找所有者的继承链,因此 before_filter 将处理 :comment thatbelongs_to :trip thatbelongs_to :user.
How do you implement code with a #require_owner method defined in ApplicationController to achieve this? Ideally, the code will look up the inheritance chain for the owner so the before_filter will work on a :comment that belongs_to :trip that belongs_to :user.
class TripsController < ApplicationController
belongs_to :member
before_filter :require_owner
...
end
推荐答案
我没有完全遵循描述(评论真的属于旅行所有者吗?),但稍微扩展了 jonnii 的回答,这里是一个例子限制行程控制器:
I don't fully follow the description (would a comment really be owned by the trip owner?), but expanding slightly on jonnii's answer, here is an example that restricts the trip controller:
class ApplicationController < ActionController::Base
...
protected
# relies on the presence of an instance variable named after the controller
def require_owner
object = instance_variable_get("@#{self.controller_name.singularize}")
unless current_user && object.is_owned_by?(current_user)
resond_to do |format|
format.html { render :text => "Not Allowed", :status => :forbidden }
end
end
end
end
class TripsController < ApplicationController
before_filter :login_required # using restful_authentication, for example
# only require these filters for actions that act on single resources
before_filter :get_trip, :only => [:show, :edit, :update, :destroy]
before_filter :require_owner, :only => [:show, :edit, :update, :destroy]
...
protected
def get_trip
@trip = Trip.find(params[:id])
end
end
假设模型如下所示:
class Trip < ActiveRecord::Base
belongs_to :owner, :class_name => 'User'
...
def is_owned_by?(agent)
self.owner == agent
# or, if you can safely assume the agent is always a User, you can
# avoid the additional user query:
# self.owner_id == agent.id
end
end
login_required
方法(由restful_authentication 或authlogic 等身份验证插件提供或依赖)确保用户已登录并为用户提供current_user
方法, get_trip
设置行程实例变量,然后在 require_owner
中检查.
The login_required
method (provided by or relying on an auth plugin like restful_authentication or authlogic) makes sure that the user is logged in and provides the user with a current_user
method, get_trip
sets the trip instance variable which is then checked in require_owner
.
只要模型已经实现了 is_owned_by?
方法,这种相同的模式几乎可以适用于任何其他资源.如果您在资源是评论时尝试检查它,那么您将在 CommentsController
中:
This same pattern can be adapted to just about any other resource, provided the model has implemented the is_owned_by?
method. If you are trying to check it when the resource is a comment, then you'd be in the CommentsController
:
class CommentsController < ApplicationController
before_filter :login_required # using restful_authentication, for example
before_filter :get_comment, :only => [:show, :edit, :update, :destroy]
before_filter :require_owner, :only => [:show, :edit, :update, :destroy]
...
protected
def get_comment
@comment = Comment.find(params[:id])
end
end
具有如下所示的 Comment
模型:
with a Comment
model that looks like:
class Comment < ActiveRecord::Base
belongs_to :trip
# either
# delegate :is_owned_by?, :to => :trip
# or the long way:
def is_owned_by?(agent)
self.trip.is_owned_by?(agent)
end
end
确保在执行此操作时检查日志,因为如果您不小心,依赖于关联的检查可能会膨胀成大量查询.
Make sure to check the logs as you are doing this since association-dependent checks can balloon into a lot of queries if you aren't careful.
这篇关于before_filter :require_owner的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!