2009-09-25 18 views
6

Dies ist mein erstes Mal mit Rails und ich fragte mich, ob es möglich ist, hat eine polymorphe Assoziation in einer SQL-Abfrage? Die Modelle und Verbindungen zwischen ihnen sind einfach genug: Eine Asset-Modell/Tabelle auf einen Gehalt beziehen kann (entweder ein Bild, Text oder Audio) über eine polymorphe Vereinigung, dhEager laden von polymorphen Assoziationen in ActiveRecord

 
class Asset < ActiveRecord::Base 
    :belongs_to :content, :polymorphic => true 
end 

und das Bild, Text, Audio sind wie folgt definiert:

 
class Image < ActiveRecord::Base 
    :has_one :asset, :as => :content 
end 

Wenn ich versuche, ein Bild zu laden, sagen wie folgt aus:

Image.first(
     :conditions => {:id => id}, 
     :include => :asset 
)

Es gibt zwei Abfragen, ein um das Bild abzurufen und eine andere die A abrufen sset (FYI, dies passiert auch, wenn ich eine :joins angeben). Soweit mir bekannt ist, macht ActiveRecord dies, weil es nicht weiß, dass es eine Eins-zu-Eins-Verbindung zwischen Image und Asset gibt. Gibt es eine Möglichkeit, eine Verbindung zu erzwingen und die 2 Objekte auf einmal zu holen? Ich habe auch versucht, Join mit einer benutzerdefinierten Auswahl zu verwenden, aber am Ende muss ich die ActiveRecord-Modelle manuell und ihre Verknüpfungen erstellen.

Bietet ActiveRecord eine Möglichkeit, dies zu tun?

Antwort

1

Nach dem Durchsuchen der Rails-Quelle habe ich festgestellt, dass Sie eine Verknüpfung erzwingen können, indem Sie eine andere Tabelle als das aktuelle Modell in den Bedingungen select, conditions oder order referenzieren.

Also, wenn ich eine Bestellung auf der Asset-Tabelle angeben:

 
Image.first(
     :conditions => {:id => id}, 
     :include => :asset, 
     :order => "asset.id" 
) 

Die resultierende SQL wird eine linke Außen verwenden beitreten und alles in einer Erklärung. Ich hätte eine innere Verbindung vorgezogen, aber ich denke, das wird für jetzt tun.

1

Ich bin selbst auf dieses Problem gestoßen. ActiveRecord lehnt sich mehr am Ende an, um es Rubyists (die vielleicht nicht einmal mit SQL vertraut sind) zu erleichtern, mit der Datenbank zu interagieren, als dies mit optimierten Datenbankaufrufen der Fall ist. Möglicherweise müssen Sie mit der Datenbank auf einer niedrigeren Ebene (z. B. DBI) interagieren, um Ihre Leistung zu verbessern. Die Verwendung von ActiveRecord beeinflusst definitiv, wie Sie Ihr Schema entwerfen.

Der Wunsch nach SQL-Effizienz hat mich über die Verwendung anderer ORMs nachdenken lassen. Ich habe keinen gefunden, der meinen Bedürfnissen entspricht. Selbst diejenigen, die sich mehr in Richtung SQL bewegen (z. B. Sequel), haben eine starke Ruby-API. Ich wäre zufrieden ohne eine Ruby-ähnliche API und nur manuell mein T-SQL schreiben. Der wirkliche Vorteil, den ich mit einem ORM habe, ist das M, das die Ergebnismenge (einer oder mehrerer Tabellen) auf die Objekte abbildet.

+0

Normalerweise verwende ich ORMs nicht mehr. Das ist eine Abstraktion, ohne die ich es gut gemacht habe. – Mario

1

(Dies ist für Rails 3 Syntax.)

MetaWhere ein geiles Juwel ist komplexe Abfragen für die Herstellung, die außerhalb von Active üblichen Domain sind einfach und Rubin-like. (@wayne:. Es unterstützt äußere als auch verbindet)

https://github.com/ernie/meta_where

Polymorphe verbindet sind ein wenig komplizierter.Hier ist, wie ich habe meine mit MetaWhere:

Image.joins(:asset.type(AssetModel)).includes(:asset) 

In der Tat, ich habe eine bequeme Methode in meiner polymorphen-Assoziations mit Klasse gemacht:

def self.join_to(type) 
    joins(:asset.type(type)).includes(:asset) 
    end 

So wird es immer abfragen & eifrig Last eine bestimmte Art von Vermögenswert. Ich habe nicht versucht, es mit mehreren Arten von Join in einer Abfrage zu mischen. Da der Polymorphismus mit demselben Fremdschlüssel arbeitet, um auf verschiedene Tabellen zu verweisen, müssen Sie ihn auf SQL-Ebene als separate Joins angeben, da ein Join nur Joins zu einer Tabelle darstellt.

Dies funktioniert nur mit ActiveRecord 3, weil Sie Zugriff auf die erstaunliche Kraft von AREL haben.

Verwandte Themen