如何为特定模型的所有ActiveRecords查询添加条件?

时间:2010-03-26 21:02:19

标签: ruby-on-rails activerecord

我使用sentient_user gem来访问我的应用程序中的current_user对象。我想覆盖默认的ActiveRecordBase查询,以将它们范围限定为当前用户。

例如,我不希望我的用户查看,删除,修改其他用户的订单。

我觉得我应该能够覆盖单个(或几个)ActiveRecordBase方法来完成此任务,但我不知道哪个或如何。

提前致谢。

2 个答案:

答案 0 :(得分:4)

在您的控制器中,使用以下查询:

@orders = current_user.orders.find(params[:id])

这将适合您的查找查询范围。您不希望在模型或ActiveRecord :: Base中包含与current_user相关的代码 - 它违反了MVC。

编辑:我应该提一下,当您需要在模型层中执行此操作时,您将使用default_scope:http://ryandaigle.com/articles/2008/11/18/what-s-new-in-edge-rails-default-scoping

例如:

class Order < ActiveRecord::Base
  default_scope :order => 'created_at DESC', :conditions => { :processed => true }
end

然后,所有Order查询将按created_at降序排序,并且只返回processed = true的记录,除非您专门覆盖其中任何一个选项。

答案 1 :(得分:1)

default_scope的主要问题是当你链接多个范围时它不再使用,所以你不能在模型中加入“当前用户范围”的逻辑。

我认为AR关联(has_many:orders)的真正用法应该只检索与在您的应用程序中执行操作的用户相关的订单。

如果您想立即保护您的对象,您可以使用授权系统(如ACL9)或实现您自己的类似,在您的情况下,放入您的模型:

# Order model
class Order < AR::Base
  belongs_to :customer

  def is_allowed_to(action, performer)
    case action
      when 'show'
        performer.id == self.customer.id
      when 'update'
        performer.id == self.customer.id
      when 'destroy'
        performer.is_a? Administrator
      ....
  end
end

然后在处理订单的控制器中,您可以使用before filter检索数据库中的实际对象,并调用方法is_allowed_to来检查权限。 action参数可以是实际的操作名称,也可以是您选择的其他名称。

我希望它会有所帮助。