1

Ich habe eine HABTM-Assoziation zwischen zwei Modellen, Benutzer und Konversation. Ich möchte in der Lage sein, die Konversationen des angemeldeten Benutzers abzufragen (current_user.conversations), die ID eines anderen Benutzers zu übergeben und eine von beiden Benutzern freigegebene Konversation zurückgeben, falls eine existiert. (ein weiterer Vorteil wäre die Abfrage erstellen haben, wenn man nicht existiert.)Modell nach Attribut der HABTM-Assoziation abfragen

Die Verbände arbeiten gut, so kann ich die dazugehörigen Objekte durch Instanzvariablen wie @user.conversations und @conversation.users zugreifen, so konnte ich den langen Weg und Schleife durch jedes Konversationsobjekt und suchen Sie die Benutzerverbände in jedem von ihnen ... Aber es muss eine effiziente Möglichkeit, diese Abfrage zu konstruieren. Was ich gerne tun könnte, ist etwas wie current_user.conversations.where(conversation.users.exists?(id: @user_id)) oder etwas wie Conversation.find(users: {id: @user_id AND current_user.id}).

Ich kann mir vorstellen, dass es eine offensichtliche Antwort darauf gibt, und ich habe hier nach ähnlichen Fragen gesucht, aber keine gefunden. Nachdem ich die Rails-API-Dokumente durchgelesen habe, stelle ich mir vor, dass die Lösung, nach der ich suche, in irgendeiner Weise mit .includes() verbunden ist, aber ich kann nicht funktionieren.

Irgendwelche Ratschläge? Vielen Dank.

+0

Können Sie ein hohes Maß Schnipsel der Modellbeziehungen zwischen den Nutzern und Gespräche posten? Hat die Konversation für jeden Benutzer einen Fremdschlüssel (z. B. "sender_id", "recipient_id")? –

Antwort

1

Angenommen, Sie haben zwei Benutzer @sender und @receiver, und es gibt eine (oder vielleicht mehr) Konversation zwischen ihnen. Eine Möglichkeit, ihre gemeinsamen Konversationen abzufragen, besteht darin, die Funktion merge in ActiveRecord zu verwenden. merge die Kreuzung der Gespräche zwischen zwischen ihnen wählen:

@shared_conversations = @sender.conversations.merge(@receiver.conversations) 

Beachten Sie, dass das Ergebnis eine Sammlung sein wird, nicht ein individuelles Gespräch. In SQL würde dies zu einem INNER JOIN übersetzen.

Wenn Sie diese Abfrage ändern möchten, um die Konversation zu erstellen, falls sie nicht existiert, können Sie first_or_create verwenden. Wie der Name schon sagt, gibt first_or_create das erste Element in der Sammlung zurück. Wenn die Sammlung leer ist, wird ein neues Objekt erstellt. Sie können es einen Block für die weitere Kontrolle über das neu geschaffene Objekt übergeben:

@shared_conversations = @sender.conversations.merge(@receiver.conversations).first_or_create do |conversation| 
    conversation.title = "#{@sender.first_name}'s conversation" 
end 

Sie können weitere Informationen auf merge in der Rails-Dokumentation finden: http://apidock.com/rails/ActiveRecord/SpawnMethods/merge.

+1

Danke, das ist genau die Art von was ich gesucht habe! Eine Sache brauchte jedoch ein wenig Überzeugungsarbeit, als ich das Äquivalent von '@ sender.conversations.merge (@ receiver.conversations) .first_or_create', anrief und die Konversation nicht existierte, sondern nur die Konversation der '@ sender' war damit verbunden. Ich habe das umgangen, indem ich die Schleife hinzugefügt habe und '@ sender.conversations.merge (@ receiver.conversations) .first_or_create do | conversation | conversation.users << @receiver ende die scheint zu funktionieren, nur wie gewünscht, Danke nochmal! –

0

Versuchen current_user.conversations.includes (: Benutzer) .wo (user.id:current_user.id)

Verwandte Themen