从头开始在消息系统上显示最后一条正文消息

Display last body message on messaging system from scratch

我在我的应用程序上用 scratchch 制作了一个消息系统。一切正常,但我只想自定义更多。所以我想在我的视图中通过 user_id 收件箱显示每个对话的最后一条消息。我有 2 个模型:对话和消息。

我只能显示这个

我迷路了。你能帮帮我吗?

messages_controller.rb

class MessagesController < ApplicationController
 before_action :authenticate_user!
  before_action do
   @conversation = Conversation.find(params[:conversation_id])
  end
def index

 @messages = @conversation.messages
  if @messages.length > 10
   @over_ten = true
   @messages = @messages[-10..-1]
  end
  if params[:m]
   @over_ten = false
   @messages = @conversation.messages
  end
 if @messages.last
  if @messages.last.user_id != current_user.id
   @messages.last.read = true;
  end
 end
@message = @conversation.messages.new
 end

private
 def message_params
  params.require(:message).permit(:body, :user_id)
 end
end

Conversations_controller.rb

class ConversationsController < ApplicationController
  before_action :authenticate_user!

  # GET /conversations
  # GET /conversations.json
  def index
    @users = User.all
    @camping = Camping.all

    # Restrict to conversations with at least one message and sort by last updated
    @conversations = Conversation.joins(:messages).distinct


  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def conversation_params
      params.require(:conversation).permit(:sender_id, :recipient_id, :user_id)
    end
end

conversation.rb

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

 belongs_to :user
  has_many :users, through: :messages


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

message.rb

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

 validates_presence_of :body, :conversation_id, :user_id

/messages/index.html.erb

 <% @messages.each do |message| %>
  <% if message.body %>

   <% user = User.find(message.user_id) %>

<%= image_tag user.avatar(:thumb), class:"imageavatarmessage" %></div>
<%= user.prenom %>
      <%= message.message_time %>
      <div class="list">
         <%= message.body %>
          <% end %>
         <% end %>

<%= form_for [@conversation, @message], html: {class: "ui reply form"} do |f| %>
   <%= f.text_area :body, class: "form-control" %>
 </div>
 <%= f.text_field :user_id, value: current_user.id, type: "hidden" %>
   <%= f.submit "Add Reply", class: "ui blue labeled submit icon button" %>
<% end %>

问题来了,我只想显示每个对话的最后一条消息。 /conversations/index.html.erb

   <% @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 %>

    <p>Conversation avec <%= link_to recipient.prenom, conversation_messages_path(conversation)%></p>
    <p><%= image_tag recipient.avatar(:small), class:"imageavatarmessage" %></p>


   <%= @conversations.last %>


    <p>Il y a <%= time_ago_in_words(conversation.updated_at)%></p>


   <% end %>
  <% end %>

我只想显示我 /conversations/index 中每个对话的最后一条消息。html.erb 我测试了这个 <%= @conversations.last %> 但它不起作用...

你能帮帮我吗?

编辑

我的消息table

:body
:conversation, index: true
:user, index: true
:read, :default => false
t.timestamps

对话table

   :sender_id
  :recipient_id
   t.timestamps
  end
 end
end

编辑 2

经过一些测试,我可以显示最后一条消息。但是这条消息对于所有对话都是一样的......我不能为每个对话都有最后一条消息。我不知道为什么...

Conversation_controller

 @conversa = Conversation.where("? IN (recipient_id, sender_id)", current_user.id)
     @test = Message.where(conversation_id: @conversa).group(:conversation_id).limit(1)

在我的 /conversations/index.html.erb

<% @test.each do |message| %>

       <%= message.body %>

 <%end%> 

我想,我接近解决方案了,你能帮帮我吗?

使用 .count 代替 .length。

@messages = @conversation.messages
if @messages.count > 10
@over_ten = true
@messages = @messages[-10..-1]
end

或者您可以这样做:

def index    
@messages = Messages.all.order("created_at DESC").limit(10)
end

如果您的 current_user 可以直接引用他们所在的相关对话,您可以像这样设置您的@conversations 变量

def index
  ...
  @conversations = current_user.conversations.joins(:messages)
end

设置完成后,您可以在索引视图中对每个进行迭代

<% @conversations.each do |conversation| %>
  <div>
    Last Message for Conversation ID:<%= conversation.id %> 
    is <%= conversation.messages.last.body %>
  </div>
<% end %>

任何想要包含最后一条消息的对话列表的人: 这是解决方案---我在 Rails 5.2.6 中完成并通过 API 我正在使用 Serializer 格式化 JSON 以获得更好的属性。

def conversations_list(user)
 @user= User.find(@user_id)  
 ids = Message.select("MAX(id) AS id")
       .group(:conversation_id).collect(&:id)
 @result = Message.order("created_at DESC").where(:id => ids)
           .joins(:conversation).order(id: :desc)
           .where("sender_id = ? OR recipient_id = ?", user.id, user.id)
           .paginate(page: params[:page],per_page:10)
    
 if @conversations.present?
  render json: {
   success: true, 
   result: ActiveModel::Serializer::CollectionSerializer.new(@result, each_serializer: ConversationSerializer),
  }
 else 
  @conversations= []
  render json: {
   success: true, 
   result: ActiveModel::Serializer::CollectionSerializer.new(@conversations, 
         each_serializer: ConversationSerializer),
     #micros: ActiveModel::Serializesr::CollectionSerializer.new(@micros, 
 each_serializer: MicroSerializer),
  }

 end 
end 

型号

# conversation.rb
  has_many :messages
  belongs_to :user
  belongs_to :sender, :foreign_key => :sender_id, class_name: 'User'
       belongs_to :recipient, :foreign_key => :recipient_id, class_name: 
       'User'
  has_one :last_message, -> { order(created_at: :DESC) },class_name: 
 "Message"

  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 

# Message.rb
   belongs_to :conversation
   belong_to :user
   validates_presence_of :body, :conversation_id, :user_id
end