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

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

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

## LINEのように日付毎に送信したメッセージを区切る方法について
作成イメージ
![ezgif.com-video-to-gif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585161/bf4a8863-4182-cfe5-9e43-76050f3c40f0.gif)


## 環境
`ruby-2.6.3`
`Rails 5.2.4.1`
## 前提として
投稿内容の自動保存機能とプレビュー機能を実装しているため、created_atによる投稿日時ではなく、updated_atを用いています。

## コード
```ruby:route.rb
  resources :groups, shallow: true do
    resources :messages
    end
  end
```

```ruby: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
```

```haml:groups/show.html.haml
    .message_contents
      = render partial:"messages/message", collection: @messages
```

```haml: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))
           
　　　　　　　　　　　　　       以下省略
```
```ruby: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でやっていること
```ruby
    @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)で並べ替えてあるため、投稿内容も早い順になっています。

次に

```ruby
    @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に相当し、その日の最初の投稿となります。
その内容からupdated_atを取得し、@first_post_timeに代入していきます。


##_message.html.hamlでやっていること
```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`に作成しています。今回は区切りの付け方ということなので、その詳細については今回は割愛します。

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


## 参考サイト
https://pikawaka.com/rails/strftime