LoginSignup
5
4

More than 3 years have passed since last update.

LINEみたくメッセージの投稿日時毎に日付で区切りを付けてみた

Posted at

初めに

2020年2月からプログラミング学習を始めたばかりの初学者です。
今回が初投稿なので、誤っている点もいくつかあるかと思いますが、暖かく見守っていただけると幸いです。
修正が必要な箇所がありましたら遠慮なくご指摘ください。

現在、チャット機能を実装中。
今回はその中で取り入れた機能の一部を備忘録も兼ねて投稿します。

LINEのように日付毎に送信したメッセージを区切る方法について

作成イメージ
ezgif.com-video-to-gif.gif

環境

ruby-2.6.3
Rails 5.2.4.1

前提として

投稿内容の自動保存機能とプレビュー機能を実装しているため、created_atによる投稿日時ではなく、updated_atを用いています。

コード

route.rb
  resources :groups, shallow: true do
    resources :messages
    end
  end
controllers/groups_controller.rb

  def show
    group = Group.find(params[:id])
    @message = Message.new
    @messages = group.messages.order(updated_at: :ASC).includes(:user, :group)
    post_dates = @messages.group_by{|post_date| post_date.updated_at.to_date}
    @first_post_time = []
    post_dates.each do |pd|
      first_pd = pd.flatten[1]
      @first_post_time << first_pd.updated_at
    end
  end
groups/show.html.haml
    .message_contents
      = render partial:"messages/message", collection: @messages
messages/_message.html.haml
  - if  @first_post_time.include?(message.updated_at) == true
    .post_datetime_area
      .datetime
        = message.post_datetime
  - if user_signed_in? && current_user.id == message.user_id
    .current_user_messages.messages_container{data: {message: {id: message.id}}}
      .message_content
        .message_updated-at
          = message.updated_at.strftime("%H:%M")
        .message_text.current_user_message_text
          = safe_join(message.text.split("\n"), tag(:br))

                    以下省略
models/message.rb
def post_datetime
    weeks = ["日","月","火","水","木","金","土"]
    post_date = self.updated_at.strftime("%Y/%m/%d")
    post_week = weeks[self.updated_at.wday]

    if post_date == Time.current.strftime("%Y/%m/%d")
      return "今日"
    elsif post_date == (Time.current - 1.days).strftime("%Y/%m/%d")
      return "昨日"
    else
      return post_date + "(#{post_week})"
    end
  end

groups_controller.rbでやっていること

    @message = Message.new
    @messages = @group.messages.order(updated_at: :ASC).includes(:user, :group)
    post_dates = @messages.group_by{|post_date| post_date.updated_at.to_date}

メッセージの一覧表示するために定義した@messagesに対してgroup_byメソッドを用いて日付毎にグルーピングしています。

post_dates = [投稿年月日①,[投稿内容1,2,3], 投稿年月日②, [投稿内容4,5]...]
このように多次元配列によって投稿年月日毎に投稿内容が格納されています。
予め昇順(updated_at: :ASC)で並べ替えてあるため、投稿内容も早い順になっています。

次に

    @first_post_time = []
    post_dates.each do |pd|
      first_pd = pd.flatten[1]
      @first_post_time << first_pd.updated_at
    end

空の配列を用意し、インスタンス変数に代入。
each文で配列を抜き出した、多次元配列をflattenメソッドで1次元配列とします。
[投稿年月日①,[投稿内容1,2,3]
       ↓
[投稿年月日①,投稿内容1,2,3]
1次元配列となったため、配列の[1]が投稿内容1に相当し、その日の最初の投稿となります。
その内容からupdated_atを取得し、@first_post_timeに代入していきます。

_message.html.hamlでやっていること

messages/_message.html.haml
  - if  @first_post_time.include?(message.updated_at) == true

if文の条件として
groupメソッドで定義した、@first_post_timeにmessage.updated_atが含まれるか否かの判定をinclude?メソッドを用いています。
trueの場合、すなわちその日の最初に投稿したものが、ある場合に
= message.post_datetime
が表示されることになります。
日付の表示方法を定義したpost_datetimeメソッドはmodels/message.rbに作成しています。今回は区切りの付け方ということなので、その詳細については今回は割愛します。

作成の流れは以上になります。
他にもっと簡単な方法やもっとこうした方が良いなどありましたらご教授いただけると幸いです。
よろしくお願いいたします。

参考サイト

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4