Rails作用域查找当前用户



我使用Rails 3与设计用户认证。假设我有一个启用了设计的用户模型和一个产品模型,并且一个用户有许多产品。

在我的产品控制器中,我希望我的find方法的作用域是current_user,即。

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

除非用户是admin用户,即current_user.admin?

现在,我几乎在每个方法中都运行了这段代码,这看起来很乱:

if current_user.admin?
  @product = Product.find(params[:id])
else
  @product = current_user.products.find(params[:id])
end

是否有更优雅/标准的方式来做这件事?

我喜欢这样做:

class Product
  scope :by_user, lambda { |user|
    where(:owner_id => user.id) unless user.admin?
  }
end

允许您在控制器中编写以下内容:

Product.by_user(current_user).find(params[:id])

如果你在很多控制器中运行这段代码,你可能应该让它成为一个before过滤器,并在你的ApplicationController中定义一个方法来做这个:

before_filter :set_product, :except => [:destroy, :index]
def set_product
  @product = current_user.admin? ? Product.find(params[:id]) : current_user.products.find(params[:id]) 
end

我不知道你用什么来确定用户是否是管理员(角色),但是如果你看CanCan,它有一个accessible_by范围,接受一种能力(一个控制用户能做什么和不能做什么的对象),并返回用户有权访问的记录基于你自己写的权限。这可能是您真正想要的,但是删除权限系统并替换它对您来说可能可行,也可能不可行。

您可以在Product上添加一个类方法,并将用户作为参数发送。

class Product < ActiveRecord::Base
  ...
  def self.for_user(user)
    user.admin? ? where({}) : where(:owner_id => user.id)
  end

那么你可以这样调用它:

Product.for_user(current_user).find(params[:id])

PS:可能有更好的方法来做where({})

最新更新