2016-10-11 2 views
1

ich den folgenden Ruby-Code verwenden:Rails: find_by_sql nutzen die falsche ID

sql = "SELECT * FROM 
     conversations 
     INNER JOIN member_users ON member_users.conversation_id = conversations.id 


     WHERE conversations.id = #{conversation.id} 
     AND member_users.user_id = #{user.id}" 

    cs = Conversation.find_by_sql(sql) 

Die Abfrage eine einzelne Zeile zurückzugibt. Aber, find_by_sql gibt die Konversation mit der ID des Mitgliedsnutzers zurück, nicht die ID der Konversation. Dies liegt daran, dass im Ergebnis zwei "id" -Spalten vorhanden sind und find_by_sql den falschen zu verwenden scheint.

Gibt es eine Möglichkeit, dies zu verhindern, ohne SELECT-Konversationen zu verwenden. * Statt SELECT *?

Warum passiert das - warum verwendet Rails nicht die erste ID-Spalte, auf die es stößt? Liegt es daran, dass die Zeile in einem Hash zurückgegeben wird?

Allgemeiner, in SQL - gibt es eine Möglichkeit, zwischen verschiedenen Spalten mit dem gleichen Namen zu unterscheiden? Oder sollen diese gleichwertig sein? Ich werde oft verwirrt, wenn ich Joins mache, die zu mehreren "id" -Spalten führen.

Danke, Louise

+0

Es ist sehr viel Aussehen zu beginnen wie [XY Problem] (http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). Warum verwenden Sie SQL anstelle von [arel] (http://guides.rubyonrails.org/active_record_querying.html)? Warum wählst du 'Conversation' aus, von dem du bereits eine Instanz hast? – TeWu

+0

Die echte Abfrage ist viel komplexer. Es ist sehr einfach in SQL zu schreiben, sehr schwierig in Arel zu schreiben. Ich neige dazu, reines SQL zu verwenden, weil a) ich in vielen verschiedenen Sprachen schreibe und nicht viele verschiedene ORMs lernen möchte und b) ich viele Anfragen schreibe, die bei Verwendung eines ORM zu langsam sind. Jüngstes Beispiel: zehn Minuten mit SQLAlchemy-Masseneinfügung, sieben Sekunden mit präparierter SQL-Zeichenfolge. – Louise

Antwort

0

ich es wie so

class MemberUser < ActiveRecord::Base 
    belongs_to :conversation_user 

    scope :users, ->(*u) { 
    where(user_id: u.flatten.compact.uniq) 
    } 

    scope :conversations, -> (*c) { 
    where(conversation_id: c.flatten.compact.uniq) 
    } 
end 

    Conversation.joins(:member_users).merge(MemberUser.users(user)) 

Was Ihre direkte Frage, warum versuchen Sie, das Gespräch zu finden, wenn Sie bereits haben finden würde?

+0

Diese Abfrage wurde für diesen Beitrag stark vereinfacht. – Louise

2

Wenn Sie eine Verknüpfung in einer find_by_sql Abfrage ausführen, mischt ActiveRecord manchmal identisch benannte Spalten aus den Tabellen. Sie können Active Hinweis richtig, indem die SELECT Klausel nur die Tabellenspalten enthalten Karte Sie interessieren.

So, Ihr Problem zu beheben, ändern Sie Ihre Abfrage mit

"SELECT conversations.* FROM conversations ..." 
+0

Von meiner Frage: "Gibt es eine Möglichkeit, dies zu verhindern, ohne SELECT-Konversationen zu verwenden. * Statt SELECT *?" Was ist, wenn ich nach einem Join mehrere Spalten aus verschiedenen Tabellen zurückgeben möchte? – Louise

Verwandte Themen