4 Stimmen

Wie sorge ich dafür, dass named_scope mit einer verknüpften Tabelle richtig funktioniert?

Das ist meine Situation. Ich habe zwei Tabellen: pledges und pledge_transactions. Wenn ein Benutzer eine Zusage macht, hat er nur eine Zeile in der Tabelle pledges.

Wenn es später an der Zeit ist, die Zusage zu erfüllen, wird jede Zahlung in meiner Tabelle pledge_transactions protokolliert.

Ich muss in der Lage sein, alle offenen Verpfändungen abzufragen, was bedeutet, dass die Summe der Beträge in der Transaktionstabelle geringer ist als der verpfändete Betrag.

Hier ist, was ich bis jetzt habe:

named_scope :open,
   :group => 'pledges.id', 
   :include => :transactions, 
   :select => 'pledge_transactions.*', 
   :conditions => 'pledge_transactions.id is not null or pledge_transactions.id is null',
   :having => 'sum(pledge_transactions.amount) < pledges.amount or sum(pledge_transactions.amount) is null'

Sie fragen sich vielleicht, warum ich diese überflüssige und lächerliche Option "Bedingungen" angegeben habe. Die Antwort ist, dass, wenn ich ActiveRecord nicht zwinge, die Tabelle pledge_transactions in den Bedingungen zu berücksichtigen, sie komplett ausgelassen wird, was bedeutet, dass meine Having-Klausel bedeutungslos wird.

Ich glaube, dass ich auf eine Schwachstelle von ActiveRecord gestoßen bin.

Letztendlich muss ich in der Lage sein, Folgendes zu tun:

  • Verpfänden.öffnen
  • Pledge.open.count
  • Pledge.open.find(:all, ...)
  • usw.

Hat jemand eine elegantere Lösung für dieses Problem? Bitte keine Vorschläge, bei denen das Feld pledges amount_given bei jeder Transaktion inkrementiert wird. Das fühlt sich wie ein Pflaster Ansatz und ich bin viel mehr von einem Fan von halten die Zusage statisch, nachdem es erstellt wird und die Berechnung der Differenz.

Wenn ich hier nicht Rails verwenden würde, würde ich einfach eine Ansicht erstellen und damit fertig sein.

Merci !

1voto

Mike Woodhouse Punkte 50241

Wie ist die :transactions Assoziation definiert? Legt sie fest :class_name = 'PledgeTransaction' (oder was auch immer die Klasse ist, wenn sie set_table_name )?

Haben Sie sich die :joins Parameter? Ich denke, das könnte das sein, wonach Sie gesucht haben. Sicherlich ist das :conditions Das sieht nicht gut aus.

Wenn ich hier nicht Rails verwenden würde, würde ich einfach eine Ansicht erstellen und damit fertig sein

Nur weil es sich um Rails handelt, heißt das nicht, dass Sie eine Ansicht nicht verwenden können. OK, je nachdem, wie sie aufgebaut ist, kann es sein, dass Sie sie nicht aktualisieren können, aber ansonsten können Sie es tun. Sie können auch Views in Migrationen erstellen und ablegen:

class CreateReallyUsefulView < ActiveRecord::Migration
def self.up
    # this is Oracle, I don't know if CREATE OR REPLACE is widely-supported
    sql = %{
      CREATE OR REPLACE VIEW really_usefuls AS
      SELECT
      ... blah blah SQL blah
    }
    execute sql
  end

  def self.down
    execute 'drop view really_usefuls'
  end
end

class ReallyUseful < ActiveRecord::Base
    # all the usual stuff here, considering overriding the C, U and D parts 
    # of CRUD if it's supposed to be read-only and you're paranoid
end

Ich denke, die Bücher/Dokumente gehen nicht so sehr darauf ein, weil die Implementierung und Unterstützung von Ansichten auf verschiedenen Plattformen sehr unterschiedlich ist.

1voto

jpoz Punkte 2237

Ich denke, mit NOT EXISTS in Ihren Bedingungen werden Sie bekommen, was Sie wollen. Ich gehe davon aus, dass die Vereinigung auf der pledge_transaction como pledge_id . So würde ich es umsetzen #open

named_scope :open,
      :conditions =>
        "
          NOT EXISTS (
            select 1
            from pledge_transactions
            where
              pledge.id = pledge_transactions.pledge_id AND
              pledge_transactions.amount < pledge.amount
            )
        "
    }
  }

Damit können Sie Pledge.open, Pledge.open.count und Pledge.open.find_by_{what ever} durchführen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X