Объекты модели, отфильтрованные владельцем, на Rails 3
Мне нужно сделать некоторую фильтрацию на моих моделях ActiveRecord, я хочу отфильтровать все мои объекты модели с помощью owner_id. Мне нужно, в основном, default_scope для ActiveRecord.
Но мне нужно фильтровать переменную сеанса, которая недоступна из модели. Я прочитал некоторые решения, но никто не работает, в основном любой из них говорит, что вы можете использовать сеанс при объявлении default_scope.
Это мое объявление для области:
class MyModel < ActiveRecord::Base
default_scope { where(:owner_id => session[:user_id]) }
...
end
Простой, правда?. Но он не говорит, что сеанс метода не существует.
Надеюсь, вы сможете помочь
Ответы
Ответ 1
Объекты сеанса в Модели считаются плохой практикой, вместо этого вы должны добавить атрибут класса в класс 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
Ответ 2
Вы не сможете включить это в 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
Этот метод все равно вернет область.
Ответ 3
Фильтрация, связанная с сеансом, представляет собой задачу пользовательского интерфейса, поэтому она имеет свое место в контроллере. (У классов модели нет доступа к циклу запроса, сеансу, файлам 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, access_by '
Также помните о пороках default_scope. rails3 default_scope и значение столбца по умолчанию при миграции