2009-08-10 18 views
2

Ich bin Neuling in Schienen und versuchen, linke Join in Mysql durchzuführen.links beitreten in Rails/mysql

gibt es zwei Objekte - Benutzer und Nachricht.

Benutzer has_and_belongs_to_many Nachrichten, Nachrichten has_and_belongs_to_many Benutzer

zur Zeit durch einfaches Schreiben user.messages i in der Konsole folgende Abfrage erhalten

SELECT * FROM `messages` INNER JOIN `messages_users` ON `messages`.id = `messages_users`.message_id WHERE (`users_messages`.group_id = 1) 

Nachricht mit eingeschränkten == false ist nicht auf einen Benutzer verbunden, sondern ist zugänglich für jeden Benutzer, und ich muss Sammlung hinzufügen.all (eingeschränkt => falsch) zu user.messages

die Abfrage, die mein Problem lösen würde wäre:

select * from messages left join messages_users on messages_users.message_id=messages.id and messages_users.user_id=1 where (messages_users.user_id is NULL and messages.restricted=false) OR (messages_users.user_id=1 and messages.restricted=true); 

Wie schreibe ich es so elegant wie möglich in Schienen?

wäre es smth wie

Message.find(:all,:conditions => "(messages_users.user_id is NULL and messages.restricted=false) OR (messages_users.user_id=1 and messages.restricted=true)", :joins => "left join messages_groups on messages_users.message_id=messages.id and messages_users.user_id=1 ") 

oder kann es schöner sein?

ich bin mit Schienen 2.3.2

Dank, Pavel

Antwort

1

Es scheint mir, dass Sie versuchen, zwei Dinge in dieser Abfrage zu ziehen: 1) alle Nachrichten nicht gebunden an einen Benutzer mit restricted = false und 2) alle Nachrichten an den aktuellen Benutzer gebunden mit restricted = true.

Wenn ich das richtig verstehe, sehe ich keinen besseren Weg, es zu tun, wenn Sie wollen, dass es als eine einzige Abfrage durchgeführt wird. Wenn Sie jedoch bereit sind, zwei Abfragen durchzuführen, können Sie diese im Code etwas aufräumen (während Sie die Ausführung möglicherweise verlangsamen). Hier ist die alternative Einrichtung:

class Message < ActiveRecord:Base 
    has_and_belongs_to_many :users 

    named_scope :restricted, :conditions => {:restricted => true} 
    named_scope :unrestricted, :conditions => {:restricted => false} 
    named_scope :public, :conditions => "id NOT IN (SELECT DISTINCT message_id FROM messages_users)" 
end 

class User < ActiveRecord:Base 
    has_and_belongs_to_many :messages 
end 

Um die Liste in weniger Code zu bekommen, aber erfordern zwei Datenbanktreffer Sie tun können:

@current_user.messages.restricted + Message.unrestricted.public 

In jedem Fall, wenn es eine erhebliche Menge an Daten, die in diesen ist Tabellen müssen Sie sicherstellen, dass sie ordnungsgemäß indexiert sind oder bei jeder Belastung langsamer werden. Wenn es sich um eine App mit vielen gesendeten Nachrichten handelt, sind Sie mit der einzelnen Abfrage wahrscheinlich besser dran. Wenn es nur eine Seitenfunktion ist, die nicht sehr oft verwendet wird, würde ich wahrscheinlich die sauberere Version nehmen.

Was aus einer Modellperspektive besser funktionieren würde, ist, die HABTM-Beziehung loszuwerden und die Beziehung explizit zu modellieren.Dann haben Sie einen praktischen Ort, um andere Daten über den Sende-/Zustell-/Empfangsprozess der Nachricht zu verfolgen (wie z. B. Sendungsverfolgungszeit, gelesene Zeit usw.). Es ändert nichts von der obigen Diskussion, ich bevorzuge nur viele bis zu HABTM.

0

denke ich named_scopes Ihre Antwort sein könnte. In Ihrem Modell wie etwas gesagt:

named_scope :restricted, :conditions => {:restricted => true} 
named_scope :unrestricted, :conditions => {:restricted => false} 

Dann können Sie Dinge nennen wie:

Message.restricted 
=> All restricted messages 

User.first.messages.unrestricted 
=> All unrestricted messages belonging to the first user. 

Ich glaube, diese Arbeit durch HABTM Verbände.

1

warum nicht verwenden: einschließen?

+0

... aber würde '' include' 'auch eine eifrige Ladung der zugehörigen Datensätze durchführen, was in der aktuellen Situation nicht wünschenswert erscheint. Das ist das Problem, das ich gerne lösen würde. – Purplejacket

Verwandte Themen