Каков общий подход к записям области действия тех, кого пользователь может «прочитать»?
Я использую Ruby on Rails 3.2.2, и я хотел бы знать, что является общим подходом, когда он должен быть проверен, если у пользователя есть надлежащие полномочия для "чтения" записи, представленные в «списке»; записей. То есть на данный момент у меня есть следующее:
class Article < ActiveRecord::Base
def readable_by_user?(user)
# Implementation of multiple authorization checks that are not easy to
# translate into an SQL query (at database level, it executes a bunch of
# "separate" / "different" SQL queries).
... # return 'true' or 'false'
end
end
Используя приведенный выше код, я могу выполнить проверку авторизации наsingle объект статьи:
@article.readable_by_user?(@current_user)
Тем не менее, когда я хотел бы сделать (обычно, в моем контроллереindex
действие) что-то вроде следующего, получая ровно 10 объектов
Article.readable_by_user(@current_user).search(...).paginate(..., :per_page => 10)
Я все еще должен выполнить проверки авторизации для каждого объекта. Так,what I can make to perform authorization checks on that "list" of records (массивArticle
объекты)in a "smart" / "performant" way? То есть, например, я должен загрузитьArticle.all
(может быть, упорядочить их по созданным данным, ограничив запрос SQL 10 записями, ...), а затем выполнить итерацию для каждого из этих объектов, чтобы выполнить проверки авторизации? или я должен сделать что-то другое (может быть, с помощью какого-то трюка с SQL-запросом, какого-либо средства Ruby on Rails или чего-то еще)?
Я пытался получить статьиreadable пользователем "вручную", например, с помощьюfind_each
метод:
# Note: This method is intended to be used as a "scope" method
#
# Article.readable_by_user(@current_user).search(...).paginate(..., :per_page => 10)
#
def self.readable_by_user(user, n = 10)
readable_article_ids = []
Article.find_each(:batch_size => 1000) do |article|
readable_article_ids << article.id if article.readable_by_user?(user)
# Breaks the block when 10 articles have passed the readable authorization
# check.
break if readable_article_ids.size == n
end
where("articles.id IN (?)", readable_article_ids)
end
В настоящее время приведенный выше код является наиболее «компромиссным вариантом». о чем я могу подумать, даже если в этом есть какая-то ошибка: это & quot;restricts& Quot; количество найденных объектов для заданного количества записей с заданнымid
s (10 записей по умолчанию в приведенном выше примере); практически говоря,it "really" doesn't retrieve all objects readable by an user с тех пор, когда вы пытаетесь расширить рамки связанныхActiveRecord::Relation
& Quot; где & Quot; / "с помощью которого"readable_by_user
используется метод области видимости (например, когда вы также будете искать статьи поtitle
добавив еще одно предложение SQL-запроса),restrict записи к темwhere("articles.id IN (?)", readable_article_ids)
(то есть «ограничивает» / «ограничивает» количество извлекаемых и читаемых объектов первыми 10 и всеми остальными статьямиreadable пользователем будет игнорироваться при поискеtitle
). Решение проблемы для того, чтобы сделатьreadable_by_user
метод для правильной работы с другими методами области может быть сделатьnot break
блок, так что загрузить всеreadable статьи, но это не годится по причинам производительности, когда записей много (возможно, другое решение - хранить где-то всю статьюid
Может быть прочитано пользователем, но я думаю, что это не общее / простое решение проблемы).
Так,there is some way to accomplish what I would like to make in a performant and "really" correct way (maybe, by changing the above approach at all)?