【问题标题】:Contextual ActiveRecord Model filtering上下文 ActiveRecord 模型过滤
【发布时间】:2009-04-24 17:01:19
【问题描述】:

在我们的网站中,有一个通用模型,比如说视频,它具有许多属性,例如私有/公共/待定、可下载等。

根据控制器、动作、请求参数和当前用户,我们希望从显示中过滤掉特定的视频。例如,在主页上,我们只想显示公开的视频。如果主页上有登录用户,我们还希望显示可下载的公开视频。

我们还想确保这些过滤器可以单独通过 sql 查询应用,这样当用户在网站上进行搜索时,我们可以使用 Sphinx 过滤掉不需要的视频。

最好通过授权插件(例如 rails-authorization-plugin)来处理?归根结底,我们的目标是防止程序员在添加新动作时意外忘记过滤掉特定视频。我们正在寻找的解决方案应该是非常程序化的。

这是我正在考虑的解决方案(尚未编写任何代码)

  1. 使用授权插件或推出我们自己的插件,允许设置显示哪些视频,在控制器或操作级别定义。

  2. 为任何具有 has_many(:videos) 或 has_one(:video) 的模型创建关联扩展,这允许我们重载关联中的视频查找器。

  3. 以类似的方式重载 Video.find 以根据当前规则限制显示的内容。

【问题讨论】:

    标签: ruby-on-rails ruby activerecord authorization


    【解决方案1】:

    您的总体策略似乎合理,但我强烈建议您不要覆盖 rails 默认查找器。相反,这是我过去做过的事情:

    class Video < ActiveRecord::Base
      named_scope :available_to, lambda {|user|
        if user.nil?
          :conditions => {:public_accessible => true}
        elsif user.omnipotent?
          {}
        else 
          :conditions => [%{
            videos.public_accessible = ? OR EXISTS (
              ....boring security stuff linking to users....
            )
          }, true, user.id]
        end 
      }
    end
    

    然后在 video_shop.rb 中:

    class VideoShop < ActiveRecord::Base
      has_many :videos 
    end
    

    最后,把它们放在一起:

    # All videos available to a user
    Video.available_to(user)
    
    # All videos in a given shop
    video_shop.videos
    
    # All videos in a given shop available to a given user
    video_shop.videos.available_to(user)
    

    请注意,即使用户为零,这些也可以工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多