Frage

ich bin Neuling in Schienen und versuchen, in mysql auszuführen LEFT JOIN.

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 von jedem Benutzer zugänglich ist, und ich brauche Sammlung Message.all (restricted => false) user.messages

hinzufügen

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 kann ich es in Schienen schreibe so elegant wie möglich?

wäre es smth wie

sein
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

Danke, Pavel

War es hilfreich?

Lösung

Es scheint mir, dass Sie zwei Dinge in dieser Abfrage zu ziehen versuchen: 1) Alle Nachrichten, die nicht an einen Benutzer gebunden mit eingeschränkten = false und 2) alle für den aktuellen Benutzer gebunden Nachrichten mit eingeschränktem = true

Wenn ich das richtig verstehen, ich sehe keinen besseren Weg, es zu tun, wenn Sie es als eine einzelne Abfrage durchgeführt werden sollen. Wenn Sie jedoch machen es zwei Anfragen an die Idee offen sind, können Sie es leicht in Code aufzuräumen (während möglicherweise die Ausführung verlangsamt). 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 können Sie tun:

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

In jedem Fall, wenn es eine erhebliche Menge an Daten in diesen Tabellen ist Sie müssen sicherstellen, dass sie korrekt indiziert sind oder dies wird mit jeder Last verlangsamen. Wenn dies ist eine App mit vielen Nachrichten sind Sie wahrscheinlich besser dran mit der einzigen Abfrage gesendet werden. Wenn es nur eine Nebenfunktion, die verwendet wird nicht sehr viel, würde ich wahrscheinlich die sauberere Version nehmen.

Was wohl aus einem Modell Perspektive besser funktionieren würde, ist die HABTM Beziehung loszuwerden und die Beziehung explizit modellieren. Dann haben Sie einen handlichen Ort verfolgt anderer Daten zu halten über die Nachrichtensende / Lieferung / Empfangsprozess (wie Tracking-Zeit gesendet, die Zeit zu lesen, usw.). Es ist nicht über eine der Diskussion ändern, ziehe ich nur viele durch HABTM hat.

class Message < ActiveRecord:Base

  has_many :subscriptions
  has_many :users, :through => :subscriptions

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

class User < ActiveRecord:Base

  has_many :subscriptions
  has_many :messages, :through => :subscriptions

end

class Subscription < ActiveRecord:Base

  belongs_to :message
  belongs_to :user

end

Andere Tipps

warum nicht verwenden: include

Ich denke, named_scopes Ihre Antwort sein könnte. In Ihrem Modell setzte so etwas wie:

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

Dann können Sie rufen Dinge wie:

Message.restricted
=> All restricted messages

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

Ich glaube, diese Arbeit durch HABTM Assoziationen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top