Rails仅在收件箱中显示来自用户的最后一条私人消息

时间:2017-10-14 09:15:40

标签: ruby-on-rails message private inbox

我创建了一个私人消息系统,但我在收件箱方面遇到了问题。 我想创建一个常规收件箱,您可以在其中查看所有对话。 我试图做一些事情,但我得到了用户得到的所有消息的结果,但我想只显示每个对话的最后一条消息。

SQL: 我得到了带有id,user_id(int),to_id(int),content(text),read(boolean)的消息表。

消息控制器:

def inbox
@messages = Message.where("to_id = ? OR user_id = ? AND to_id != 0", current_user, current_user).order(created_at: :desc)
end

查看:

<% @messages.each do |message| %>
    <% to_user_id = User.find(message.to_id) %>
    <% to_user_name = to_user_id.username %>
    <b><p><%= to_user_name %></p></b>
    <p>
    <% if message.read == false %>
      <b><%= link_to message.content, pm_path(to_user_id) %></b>
    <% else %>
      <%= link_to message.content, pm_path(to_user_id) %>
    <% end %>
    </p>
  <% end %>

希望我很清楚,并提前感谢你。

2 个答案:

答案 0 :(得分:0)

尝试这个

@messages = Message.find_by("(to_id = ? OR user_id = ?) AND to_id != 0", current_user, current_user).order(created_at: :desc)

答案 1 :(得分:0)

如果正确设置关联,则很简单:

class User < ApplicationRecord
  has_many :recieved_messages, class_name: 'Message', foreign_key: 'recipent_id'
  has_many :sent_messages, class_name: 'Message', foreign_key: 'sender_id'

  def all_messages
    Message.where('recipient_id = :id OR sender_id = :id', id: id)
  end
end

class Message < ApplicationRecord
  belongs_to :recipient, class_name: 'User', inverse_of: :recieved_messages
  belongs_to :sender, class_name: 'User', inverse_of: :sent_messages

  def self.between(a,b)
    .where('(recipient_id = :id OR sender_id = :id)', id: a)
    .where('(recipient_id = :id OR sender_id = :id)', id: b)
  end
end

# all messages recieved by the current user:
current_user.recieved_messages.order(created_at: :desc)

# all messages recieved by the current user:
current_user.sent_messages.order(created_at: :desc)

# all messages sent or recieved by the current user:
current_user.all_messages.order(created_at: :desc)

# all messages between two users
Message.between(current_user, some_other_user)

向用户传达任何信息的关键是:

WHERE (recipient_id = a OR sender_id = a) AND (recipient_id = b OR sender_id = b)

但你应该考虑创建一个会话模型来加入它们。

调用.last将获得最早的记录,因为它按降序排列。如果您想要最新消息,请使用.first

要避免N + 1查询问题,请确保加载相关记录:

@messages.eager_load(:recipient, :sender)

迭代时(通常)使用关联而不是ids。切勿执行User.find(message.to_id)之类的操作,因为这会导致N + 1查询问题。

<% @messages.each do |message| %>
  <p><b><%= message.recipent.name %></b></p>
  <p>
    <% if message.read? %>
      <%= link_to message.content, pm_path(message.recipient) %>
    <% else %>
      <b><%= link_to message.content, pm_path(message.recipient) %></b>
    <% end %>
  </p>
<% end %>