2015-06-20 138 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