2015-06-20 116 views
1

我正在軌道4上創建一個簡單的聊天應用程序。控制器,模型和視圖已創建,但功能仍不完整。我在我的數據庫中有兩個表格,會話和消息。會話表包含兩個字段,發件人ID和收件人ID。消息表包含3個字段,正文,用戶標識和讀取(默認爲0,表示不讀取)。未讀消息計數器

型號:

class Conversation < ActiveRecord::Base 

    belongs_to :sender, :foreign_key => :sender_id, :class_name => "User" 
    belongs_to :reciever, :foreign_key => :reciever_id, :class_name => "User" 

    has_many :messages, :dependent => :destroy 

    validates_uniqueness_of :sender_id, :scope => :reciever_id 

    scope :involving, lambda { |user_id| 
     where("sender_id = ? OR reciever_id = ?", user_id, user_id) 
    } 

    scope :between, lambda { |sender_id, reciever_id| 
     where("(sender_id = ? AND reciever_id = ?) OR (sender_id = ? AND reciever_id = ?)", sender_id, reciever_id, reciever_id, sender_id) 
    } 

    def other_interlocutor(user_id) 
     if sender.id == user_id 
      return reciever.id 
     else 
      return sender.id 
     end 
    end 
end 

class Message < ActiveRecord::Base 
    belongs_to :conversation 
    belongs_to :user 

    validates_presence_of :conversation_id, :user_id, :body 

end 

我所要做的就是創建接收未讀郵件的實時功能計數,每當有人收到新的消息。我正在使用私人酒吧來創建用戶之間的聊天。

我有一個包含此功能的用戶模式:

def unread_messages_count 
    unread_messages = 0 
    # puts "Putting self conversations ! #{self.conversations.first}" 
    conversations = Conversation.involving(self.id) 
    conversations.each do |conversation| 
     unread_messages += conversation.messages.where(:read => 0, :user_id => conversation.other_interlocutor(self.id)).count 
    end 
    return unread_messages = unread_messages == 0 ? nil : unread_messages 
end 

我有一個頁面,所有用戶的通話列和一個對話被點擊所有與該對話的信息都被列出了。在同一頁上,我訂閱了每個conversation_messages_path爲每個對話創建單獨的頻道。每當一個消息被髮送一個create.js.erb文件呈現在我發佈這些訂閱的頻道:

<% publish_to conversation_messages_path(@conversation.id) do %> 
    $("#conversations_link").text("<%= current_user.unread_messages_count %> Conversations"); 
    $("#messages").append("<%= escape_javascript render(:partial => 'message', :locals => { :message => @message })%>"); 
<% end %> 

$("#conversation_link")是我想要顯示的未讀郵件數。

當前,未讀郵件數正在返回錯誤計數,並且導航欄僅在conversation.sender_id消息接收方更新。

我的未讀消息計數器未返回正確數量的未讀消息。我不知道如何解決它。我的代碼有什麼問題? 謝謝。

+0

「我的代碼出了什麼問題,我應該怎麼做才能使這件事情起作用?」作爲一個問題陳述,這個陳述非常模糊和不具描述性。與其傾倒大量的大量代碼,不如試圖將問題孤立於可以切實解決的問題上? – MarsAtomic

+0

@MarsAtomic所有代碼都是必需的,以便了解我的應用中發生了什麼。 –

回答

3

我認爲你的領域建模確實是關閉的。

對話的整個想法是有關各方輪流成爲發件人和收件人。你所建模的是一個獨白

獨白是一個人發表的演講,或是一段長長的單方面的談話,讓你想把你的頭髮從無聊中拉出來。 希臘詞根monologos翻譯爲「獨自說話」,並且這是一個獨白:一個人在做所有的談話。

你結束了這裏的域模型應該是這個樣子:

database diagram

它,實際上是鏈接到兩個用戶(或更多)的消息:senderrecipient。爲了簡單起見,我在這裏堅持使用1:1的消息傳遞(對羣組消息來說,消息可能屬於許多收件人)。

class Message 
    belongs_to :recipient, class_name: 'User' 
    belongs_to :sender, class_name: 'User' 
end 

class User 
    has_many :sent_messages, 
      class_name: 'Message', 
      foreign_key: 'sender_id' 
    has_many :messages, foreign_key: 'recipient_id' 
end 

請注意,當它不能從關聯名稱派生時,我們需要告訴Rails類和外鍵。

取而代之的是布爾型read字段,您可能需要考慮使用enum來表示消息的狀態。

枚舉基本上是一個整數列映射到符號列表。

class Message 
    enum :status, [:unread, :read] 
    belongs_to :recipient, class_name: 'User' 
    belongs_to :sender, class_name: 'User' 
    belongs_to :conversation 
end 

枚舉給你作用域,如:

Message.unread 
Message.read 

和條件,如:

message.unread? 
message.read? 

而且這使得它,如果你想添加等更多的國家如:archieved或非常簡單:trashed

有了這個武裝,你不需要你的unread_messages_count怪物。由於您將記錄從數據庫中拉出來以計算相關記錄,因此這會佔用大量內存。

current_user.messages.unread.size 

此外,我們應該正確地定義用戶和會話之間的關係:

class Conversation 
    has_many :messages 
    has_and_belongs_to_many :users 
end 

class Users 
    # .. 
    has_and_belongs_to_many :conversations 
end 

has_and_belongs_to_many關係將存儲用戶和converstations在users_conversations連接表。您可以使用下面的生成器來創建連接表遷移:

rails generate migration users_conversations 

補充:

使用你的觀點session[:user_id]是一個非常糟糕的代碼味道。您將您的身份驗證邏輯緊密結合到您的應用程序中。

而是創建一個幫助:

class SessionsHelper 
    def current_user 
    @current_user ||= User.find(session[:user_id]) 
    end 

    def user_signed_in? 
    !current_user.nil? 
    end 
end 

應用程序的其他部分不應該知道,你的當前用戶存儲在session[:user_id]只是有一個current_user

+2

我希望在這裏不要過分磨損 - 我的目標不是批評你的能力,而是告訴你,你的問題是由於設計中的一些基本缺陷。我第一次構建了一個消息傳遞系統,這真是一個廢話... – max

+0

我需要獲得一個用戶的對話,他是收件人或發件人。我將如何使用這個模型做到這一點? –

+0

只要做'user.conversations' – max