2016-10-25 2 views
0

Ich habe ein Tutorial verfolgt, um Benutzern zu ermöglichen, sich gegenseitig Nachrichten in meiner App zu senden. Ich verwende ein Gerät zur Authentifizierung. Wenn zwei oder mehr Benutzer Unterhaltungen zwischen ihnen haben und einer oder mehrere Benutzer ihren Account abbrechen, können die verbleibenden Benutzer nicht mehr auf die Indexseite für Konversationen zugreifen. Ich bekomme ActiveRecord::RecordNotFound in ConversationsController#index.Wenn Benutzer Nachrichten zwischen ihnen haben und ein Benutzer sein Konto löscht, kann der andere Benutzer nicht mehr auf den Nachrichtenindex in Rails zugreifen.

Der Code in Fettschrift ist, wo der Fehler identifiziert wurde. Was wäre der beste Weg, dies zu lösen?

Vielen Dank im Voraus

Index Ansicht:

<% @conversations.each do |conversation| %> 
    <% if conversation.sender_id == current_user.id || conversation.recipient_id == current_user.id %> 
    <% if conversation.sender_id == current_user.id %> 
     **<% recipient = User.find(conversation.recipient_id) %>** 
    <% else %> 
     <% recipient = User.find(conversation.sender_id) %> 
    <% end %> 
    <tr> 
     <td><%= link_to (image_tag recipient.avatar.url, size: "50x50"), user_path(recipient) %></td> 
     <td><%= recipient.full_name %></td> 
     <td><%= link_to "View Message", conversation_messages_path(conversation) %></td> 
    </tr> 
    <% end %> 
<% end%> 

Der Controller:

class ConversationsController < ApplicationController 
    def index 
    @users = User.all 
    @conversations = Conversation.all 
    end 

    def create 
    if Conversation.between(params[:sender_id],params[:recipient_id]) 
    .present? 
     @conversation = Conversation.between(params[:sender_id], 
     params[:recipient_id]).first 
    else 
    @conversation = Conversation.create!(conversation_params) 
    end 
    redirect_to conversation_messages_path(@conversation) 
    end 

    private 
    def conversation_params 
    params.permit(:sender_id, :recipient_id) 
    end 
    end 

Das Modell:

class Conversation < ActiveRecord::Base 
    belongs_to :sender, :foreign_key => :sender_id, class_name: 'User' 
    belongs_to :recipient, :foreign_key => :recipient_id, class_name: 'User' 

    has_many :messages, dependent: :destroy 

    validates_uniqueness_of :sender_id, :scope => :recipient_id 

    scope :between, -> (sender_id,recipient_id) do 
    where("(conversations.sender_id = ? AND conversations.recipient_id =?) OR (conversations.sender_id = ? AND conversations.recipient_id =?)", sender_id,recipient_id, recipient_id, sender_id) 
    end 
end 
+0

Sie sollten Ihren Controller und Modell als auch Post ändern. Das Anzeigen der Indexansicht selbst hilft den Benutzern nicht, den Fehler zu erkennen. – angkiki

Antwort

0

Ja, es ist ein Problem, und Sie haben viele Anrufe, die auf den nicht vorhandenen Benutzerdatensätzen erfolgen.

Ich würde vorschlagen, Sie ersetzen ...

recipient = User.find(conversation.recipient_id) 

und

recipient = User.find(conversation.sender_id) 

mit ...

recipient = get_the_user(conversation.recipient_id) 
recipient = get_the_user(conversation.sender_id) 

Sie werden eine Hilfsmethode benötigen ... Sie kann es in Ihre ApplicationController

setzen

Und wie Sie nicht auf die nicht vorhandene Benutzer verknüpfen können,

<%= link_to (image_tag recipient.avatar.url, size: "50x50"), user_path(recipient) %> 

in

<%= recipient.class == User ? link_to (image_tag recipient.avatar.url, size: "50x50"), user_path(recipient) : 'no link available' %> 
+0

Btw @Maurice das ist Lösung (1) in meiner Antwort. Ich sage nicht, dass es falsch ist, es ist ein perfektes Beispiel dafür, Dinge anders zu machen - je nachdem, was Sie wollen und brauchen. In diesem Fall: Wenn ein Benutzer mit Ihrem Service nicht zufrieden ist und seinen Account löscht, werden seine Nachrichten nicht gelöscht. – everyman

0

Hängt davon ab, was Sie wollen:

  1. Benutzer sollte als "gelöscht" markiert werden, aber die Nachricht ist lesbar.
  2. Wenn einer der Benutzer gelöscht wird, wird auch die Nachricht zerstört.
  3. Nachricht ist für die Benutzer nicht lesbar, aber admins ... (schlechteste Idee, die ich denken kann)

Imo (2) ist der Weg zu gehen. User Modell sollte so etwas wie haben:

has_many :conversations, dependent: :destroy 

Und imo Ihre Frage ist fundamentaler als Sie denken. Bei der Software-Entwicklung geht es oft mehr um Entscheidungen als um das Schreiben von Code.

+0

Ich habe Lösung Nummer 2 versucht, aber das funktioniert auch nicht :-( – Maurice

+0

Haben Sie Ihre Testdaten zurückgesetzt?(Das geht natürlich nicht, wenn die Konversation, die sich auf ein gelöschtes Objekt bezieht, noch existiert) – everyman

+0

Das habe ich mir auch gedacht und es ausprobiert, aber es hat nicht funktioniert. Die Lösung von @steveturczyn funktionierte, musste nur ein wenig zwicken – Maurice

Verwandte Themen