1

我需要对我的 ActiveRecord 模型进行一些过滤,我想通过 owner_id 过滤我的所有模型对象。我需要的基本上是 ActiveRecord 的 default_scope。

但我需要按一个会话变量进行过滤,该变量无法从模型中访问。我已经阅读了一些解决方案,但没有一个有效,基本上它们中的任何一个都说您可以在声明 default_scope 时使用会话。

这是我对范围的声明:

class MyModel < ActiveRecord::Base
    default_scope { where(:owner_id => session[:user_id]) }
    ...
end

很简单,对吧?但它没有说方法会话不存在

希望你能帮忙

4

3 回答 3

3

模型中的会话对象被认为是不好的做法,相反,您应该根据 current_user 向您在 中User设置的类添加一个类属性around_filterApplicationController

class User < ActiveRecord::Base

    #same as below, but not thread safe
    cattr_accessible :current_id

    #OR

    #this is thread safe
    def self.current_id=(id)
      Thread.current[:client_id] = id
    end

    def self.current_id
      Thread.current[:client_id]
    end  

end

在你ApplicationController做的:

class ApplicationController < ActionController::Base
    around_filter :scope_current_user  

    def :scope_current_user
        User.current_id = current_user.id
    yield
    ensure
        #avoids issues when an exception is raised, to clear the current_id
        User.current_id = nil       
    end
end

现在MyModel您可以执行以下操作:

default_scope where( owner_id: User.current_id ) #notice you access the current_id as a class attribute
于 2013-03-07T19:45:57.560 回答
0

您将无法将其合并到 default_scope 中。由于没有会话,这将破坏(例如)控制台内的所有使用。

你可以做什么:添加一个方法让你的 ApplicationController 像这样

class ApplicationController
  ...
  def my_models
    Model.where(:owner_id => session[:user_id])
  end
  ...

  # Optional, for usage within your views:
  helper_method :my_models
end

无论如何,此方法将返回一个范围。

于 2012-05-21T09:35:51.217 回答
0

与会话相关的过滤是一个 UI 任务,因此它在控制器中占有一席之地。(模型类无权访问请求周期、会话、cookie 等)。

你想要的是

# my_model_controller.rb
before_filter :retrieve_owner_my_models, only => [:index] # action names which need this filtered retrieval

def retrieve_owner_my_models
   @my_models ||=  MyModel.where(:owner_id => session[:user_id])
end

由于按当前用户的所有权进行过滤是一种典型情况,也许您可​​以考虑使用标准解决方案,例如搜索“cancan gem,accessible_by”

还要注意 default_scope 的弊端。rails3 default_scope,以及迁移中的默认列值

于 2012-05-21T09:40:04.333 回答