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]
War es hilfreich?

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:

  1. 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;
  2. 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 

Sie können fusionieren Methode, um Bereiche von verschiedenen Modellen zu verschmelzen. Weitere Einzelheiten zur Zusammenführung in diesem Railscast

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)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top