我需要对ActiveRecord模型进行一些过滤,我想通过owner_id过滤我的所有模型对象。我需要的东西基本上是ActiveRecord的default_scope。
但我需要通过会话变量进行过滤,该变量无法从模型中访问。我读过some solutions,但都没有用,基本上任何一个都说你可以在声明default_scope时使用session。
这是我对范围的声明:
class MyModel < ActiveRecord::Base
default_scope { where(:owner_id => session[:user_id]) }
...
end
简单,对吧?但它没有说方法会话不存在。
希望你能帮忙
答案 0 :(得分:3)
模型中的会话对象被认为是不好的做法,而是应该为User
类添加一个类属性,您可以在around_filter
中的ApplicationController
中根据CURRENT_USER
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
答案 1 :(得分: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
无论如何,此方法将返回范围。
答案 2 :(得分: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, and default column value in migration