before_filter :require_owner [英] before_filter :require_owner

查看:30
本文介绍了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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆