Объекты модели, отфильтрованные владельцем, на 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 и значение столбца по умолчанию при миграции