Rails ToDoアプリ タスク管理アプリ (期限切れ・締め切り順・完了ボタン)

#  はじめに
雑記事です。また時間を見つけてブラッシュアップいたします。

##完成図
![スクリーンショット 2022-02-19 6.33.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1081227/f9517dd6-6b17-785d-7b13-1948c146b7a2.png)

・タスク一覧に残り期限が表示されている
・タスク一覧にタスクが期限順に並んでいる
・期限切れの未完了タスクの表示を変更している
・未完了タスクに完了ボタンが表示されている
・完了ボタンを押すと、完了したタスク一覧に完了日時が表示される




##前提
タスクの簡単なタイトル投稿が作成済みであること
Railsの基礎的な知識を身につけていること


##実装方法
まずタスクを保存する該当のテーブル(本記事ではtweetsテーブル)にタスクの期限を格納するtimeカラムと、タスクが完了した日を格納するdone_atカラムを追加する

### データベース

以下のコマンドでマイグレーションファイルを生成します。

```irb
$ rails g migration add_columns_to_tweets
```

生成されたマイグレーションファイルに以下の2行を追記しましょう。

```ruby:db/〇〇_add_columns_to_tweets.rb
class AddColumnsToTweets < ActiveRecord::Migration[6.1]
  def change
      add_column :tweets, t.date :time #追記
      add_column :tweets, t.datetime :done_at #追記
  end
end

```

```irb
$ rails db:migrate
```

### コントローラー
タスクに関するところはコメントアウトを残しています。
作成中のサイトに合う形で追記or修正してください。

```tweets_controller.rb
class TweetsController < ApplicationController
  def index
    @today = Date.today #今日の日付
    @tweet = Tweet.new
    @tweets = Tweet.where(done_at:nil).order(:time) #未完了タスクかつ期限が近い順に並べ替え
    @tweets_done = Tweet.where.not(done_at:nil) #完了タスク
  end
  
  def create
    tweet = Tweet.new(tweet_params)
    if tweet.save
      redirect_to :action => "index"
    else
      redirect_to :action => "new"
    end
  end
  # ↓↓↓今回のPOINT↓↓↓
  def done
    @today = Date.today #今日の日付
    tweet = Tweet.find(params[:id])
    tweet.update(done_at: @today ) #完了ボタンを押すとdone_atカラムに完了した日時を追加
    redirect_to :action => "index"
  end

  private
  def tweet_params
    params.require(:tweet).permit(:time,:title,:done_at) #カラムの追加をお忘れなく
  end
end

```

###ルート
以下を追記してください

```ruby:routes.rb
  post '/tweets/:id/done' => 'tweets#done',   as: 'done'
```
###ビュー
タスクに関するところはコメントアウトを残しています。
作成中のサイトに合う形で追記or修正してください。

※改行タグを乱用して見栄えを整えようとしている点、ご了承くださいませm(_ _)m

```erb:tweets/index.html.erb
<h1>Tweets#index</h1>
<%= form_for @tweet do |f| %>
    <%= f.label :タスク名 %>
    <%= f.text_field :title, :size => 40 %></br>
    <%= f.label :締切 %>
    <%= f.date_field :time, :size => 140 %>
  <%= f.submit "Tweetする" %>
  <% end %>

<div class="tweet-container"%>
  <div class="item"%>
    <h1>タスク一覧</h1>
    <% @tweets.each do |t| %> #@tweetsの中身は未完了タスク
      <div class="tweet">
      <% if (t.time - @today).to_i > -1 %> #期限が切れていないタスクの表示
        タスク名:<b><%= t.title %></b></br>
        締切:<%= t.time %></br>
        残り:<%= (t.time - @today).to_i %>日</br> #残り日数を計算
        <%= button_to 'Done', done_path(t.id), method: :post %></br></br> #タスク完了ボタン
      <% else %> #期限が切れているタスクの表示
        <b><%= t.title %></b></br>
        締切:<%= t.time %></br>
        <%= (t.time - @today).to_i * -1 %>日期限が超過しています😀</br> #何日期限超過かを計算
        <%= button_to 'Done', done_path(t.id), method: :post %></br></br> #タスク完了ボタン
      <% end %>
      </div>
    <% end %>
  </div>
  <div class="item"%>
  <h1>完了したタスク</h1>
    <% @tweets_done.each do |t| %> #@tweets_doneの中身は完了タスク
      <div class="tweet">
        タスク名:<b><%= t.title %></b></br>
        完了日:<%= t.done_at.strftime('%Y-%m-%d') %> </br></br> #完了日の表示
      </div>
    <% end %>
  </div>
</div>

```

###CSS(蛇足)
タスク一覧と完了タスク一覧を横並びにしているだけです。

```scss:tweets.scss
.tweet-container{
  display: flex;
  flex-direction: row;
  justify-content: center;
}
.item{
  width: 40%;
}
```

####このようにできていれば完成です。
![スクリーンショット 2022-02-19 6.33.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1081227/f9517dd6-6b17-785d-7b13-1948c146b7a2.png)

###最後に
とても雑な記事なので編集リクエストなどドシドシお待ちしております。
少しでも開発の手助けとなれば幸いです。
以上、ここまで読んでいただきありがとうございました(^^)