Was ist ein üblicher Ansatz, um Datensätze zu erfassen, die ein Benutzer „lesen“ kann?

Ich verwende Ruby on Rails 3.2.2 und möchte wissen, was ein gängiger Ansatz ist, wenn überprüft werden muss, ob ein Benutzer über die erforderlichen Berechtigungen zum "Lesen" von Datensätzen in einer "Liste" von Datensätzen verfügt. Das heißt, zu diesem Zeitpunkt habe ich Folgendes:

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

Mit dem obigen Code kann ich Berechtigungsprüfungen für a durchführenSingle Artikelobjekt:

@article.readable_by_user?(@current_user)

Allerdings, wenn ich machen möchte (in der Regel in meinem Controllerindex Aktion) durch Abrufen von genau 10 Objekten

Article.readable_by_user(@current_user).search(...).paginate(..., :per_page => 10)

Ich muss noch Berechtigungsprüfungen für jedes Objekt durchführen. So,Was kann ich tun, um Berechtigungsprüfungen für diese "Liste" von Datensätzen durchzuführen? (ein Array vonArticle Objekte)"klug" / "performant"? Das soll ich zum Beispiel ladenArticle.all (Ordnen Sie diese nach erstellten Daten, beschränken Sie die SQL-Abfrage auf 10 Datensätze, ...) und wiederholen Sie dann jedes dieser Objekte, um Berechtigungsprüfungen durchzuführen. oder sollte ich etwas anderes machen (vielleicht mit einem SQL-Abfragetrick, einer Ruby on Rails-Funktion oder etwas anderem)?

AKTUALISIERT nach @Matzi Antwort

Ich habe versucht, Artikel abzurufenlesbar von einem Benutzer "manuell", zum Beispiel mit derfind_each Methode:

# 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

Zu diesem Zeitpunkt ist der obige Code der "performanteste Kompromiss", den ich mir vorstellen kann, auch wenn er eine Tücke hat: "einschränktmsgstr "die Anzahl der abgerufenen Objekte zu einer bestimmten Anzahl von Datensätzen mit"ids (standardmäßig 10 Datensätze im obigen Beispiel); praktisch gesprochen,Es werden nicht "wirklich" alle Objekte abgerufen, die von einem Benutzer gelesen werden können seit wann versuchst du das verwandte weiter auszuweitenActiveRecord::Relation "wo" / "mit welcher" diereadable_by_user Die scope - Methode wird verwendet (zum Beispiel, wenn Sie Artikel auch nach suchen würden)title Hinzufügen einer weiteren SQL-Abfrageklausel)beschränken Aufzeichnungen zu diesenwhere("articles.id IN (?)", readable_article_ids) (Das heißt, es "begrenzt" / "beschränkt" die Anzahl der abgerufenen und lesbaren Objekte auf die ersten 10 und alle anderen Artikellesbar vom Benutzer wird bei der Suche nach ignorierttitle). Eine Lösung für das Problem, um das zu machenreadable_by_user Methode, um mit weiteren Scope-Methoden richtig zu arbeiten, könnte sein, zu tunnicht break der block lädt also alleslesbar Artikel, aber es ist aus Performancegründen nicht gut, wenn es viele Datensätze gibt (vielleicht könnte eine andere Lösung darin bestehen, alle Artikel irgendwo zu speichernids für einen Benutzer lesbar, aber ich denke, es ist keine übliche / einfache Lösung, um das Problem zu lösen).

So,Gibt es eine Möglichkeit, das, was ich machen möchte, auf eine performante und "wirklich" korrekte Art und Weise zu erreichen (möglicherweise, indem ich den obigen Ansatz überhaupt ändere)?

Antworten auf die Frage(5)

Ihre Antwort auf die Frage