Wie beurteilen Sie Umfang Active Verbände in Rails 3?
-
18-09-2019 - |
Frage
Ich habe eine Rails 3 Projekt. Mit Rails 3 kam Arel und die Fähigkeit, einen Umfang wiederzuverwenden andere zu bauen. Ich frage mich, ob es einen Weg gibt, Bereiche zu verwenden, wenn eine Beziehung definieren (beispielsweise ein „has_many“).
Ich habe Aufzeichnungen, die Erlaubnis Spalten haben. Ich möchte einen default_scope bauen, die meine Erlaubnis Spalten berücksichtigt, so dass Aufzeichnungen (auch die durch eine Beziehung zugegriffen wird) gefiltert werden.
Derzeit in Rails 3, default_scope (einschließlich Patches ich gefunden habe) bieten nicht ein praktikables Mittel eine proc zugeben (was ich für späte Variable benötigen Bindung). Ist es möglich, kann eine has_many, in denen ein benannte Umfang weitergegeben zu definieren?
Die Idee einen benannten Umfang der Wiederverwendung würde wie folgt aussehen:
Orders.scope :my_orders, lambda{where(:user_id => User.current_user.id)}
has_many :orders, :scope => Orders.my_orders
oder implizit in der Beziehung mit dem Namen Umfang Codierung würde wie folgt aussehen:
has_many :orders, :scope => lambda{where(:user_id => User.current_user.id)}
Ich versuche einfach default_scope mit dem späten Bindung anzuwenden. Ich würde es vorziehen, einen Arel Ansatz zu verwenden (wenn vorhanden), aber würde jede praktikable Option.
Da ich auf die aktuellen Benutzer beziehen mich, ich kann nicht auf Bedingungen stützen, die im letztmöglichen Moment ausgewertet werden nicht, wie zum Beispiel:
has_many :orders, :conditions => ["user_id = ?", User.current_user.id]
Lösung
Ich schlage vor, Sie nehmen einen Blick auf "Scopes sind tot "
Der Autor erklärt es, wie mächtig Arel ist:)
Ich hoffe, es hilft.
EDIT # 1. März 2014
Da einige Kommentare Zustand, der Unterschied ist jetzt eine Frage des persönlichen Geschmacks.
Allerdings habe ich persönlich noch empfehlen Arel des Umfang eine obere Schicht auszusetzen (wobei ein Controller oder irgendetwas anderes, das die Modelle direkt zugreifen), und tun würde dies erfordern:
- Erstellen Sie einen Rahmen, und setzen Sie es durch ein Verfahren in Ihrem Modell. Diese Methode wäre diejenige, die Sie an die Steuerung aussetzen;
- Wenn Sie nie Ihre Modelle auf Ihren Controllern aussetzen (so Sie irgendeine Art von Service-Schicht auf sie haben), dann bist du gut. Die Anti-Korruptions-Schicht ist Ihr Service und es kann zu viel Ihres Modells Umfang zugreifen, ohne sich Gedanken darüber, wie Bereiche umgesetzt werden.
Andere Tipps
Wie wäre es Assoziation Erweiterungen?
class Item < ActiveRecord::Base
has_many :orders do
def for_user(user_id)
where(user_id: user_id)
end
end
end
Item.first.orders.for_user(current_user)
UPDATE: Ich möchte den Vorteil zu Verein Erweiterungen darauf hinzuweisen, wie auf Klassenmethoden oder Bereiche im Gegensatz ist, dass Sie den Zugriff auf die Interna des Vereins Proxy haben:
proxy_association.owner gibt das Objekt, dass der Verband ein Teil ist. proxy_association.reflection gibt das Reflexionsobjekt, das die Vereinigung beschreibt. proxy_association.target gibt das zugehörige Objekt für belongs_to oder has_one, oder die Sammlung von zugehörigen Objekten für has_many oder has_and_belongs_to_many.
Weitere Informationen finden Sie hier: http://guides.rubyonrails.org/association_basics.html# Verband-Erweiterungen
Statt Bereiche habe ich nur Klasse-Methoden wurden definiert, die große gearbeitet hat,
def self.age0 do
where("blah")
end
Ich benutze so etwas wie:
class Invoice < ActiveRecord::Base
scope :aged_0, lambda{ where("created_at IS NULL OR created_at < ?", Date.today + 30.days).joins(:owner) }
end
Wenn Sie nur versuchen, die Benutzer-Aufträge zu bekommen, warum Sie nicht nur die Beziehung verwenden?
Vorausgesetzt, dass der aktuelle Benutzer von der current_user Methode in Ihrem Controller zugänglich ist:
@my_orders = current_user.orders
Dies stellt sicher, nur einen bestimmten Aufträge des Benutzers angezeigt werden. Sie können auch beliebig verschachtelt Sie schließt sich durch die Verwendung joins
tiefer Ressourcen zu bekommen
current_user.orders.joins(:level1 => { :level2 => :level3 }).where('level3s.id' => X)