Контекстная фильтрация модели ActiveRecord - PullRequest
1 голос
/ 24 апреля 2009

На нашем сайте есть общая модель, скажем, Video, которая имеет ряд атрибутов, таких как private / public / pending, загружаемые и т. Д.

На основе контроллера, действия, параметров запроса и текущего пользователя мы хотим отфильтровать определенные видео с дисплея. Например, на главной странице мы хотим показывать только общедоступные видео. Если на главной странице есть зарегистрированный пользователь, мы также хотим показывать общедоступные загружаемые видео.

Мы также хотим убедиться, что эти фильтры могут применяться только через SQL-запросы, чтобы с помощью Sphinx мы могли отфильтровывать нежелательные видео, когда пользователь выполняет поиск на сайте.

Это лучше всего обрабатывается через плагин авторизации, такой как rails-authorization-plugin? В итоге наша цель - не дать программистам случайно забыть отфильтровать определенные видео при добавлении нового действия. Решение, которое мы ищем, должно быть очень программным.

Вот решение, о котором я думаю (еще не написал код)

  1. Используйте плагин авторизации или разверните наш собственный, который позволяет установить, какие видео будут отображаться, определенные на уровне контроллера или действия.

  2. Создайте расширение ассоциации для любой модели has_many (: videos) или has_one (: video), что позволяет нам перегружать искатель для видео в ассоциации.

  3. Перегрузить Video.find аналогичным образом, чтобы ограничить отображаемое содержимое в соответствии с текущими правилами.

1 Ответ

3 голосов
/ 30 апреля 2009

Ваша общая стратегия кажется разумной, но я настоятельно рекомендую вам не отменять поиск по умолчанию для 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)

Обратите внимание, что они работают, даже если пользователь nil.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...