【Rails】開始時刻と終了時刻を保存する

# 開始時刻と終了時刻を保存する
railsで、タスクの開始時刻と終了時刻を保存するプログラムを作ります。
自己流の部分が多いので、あくまでやり方の１つとして参考にしてくださると幸いです。
※今回は、開始、終了時刻を保存することをメインに扱います。削除、編集機能や見た目は勘弁してください。

![画面収録 2020-09-25 2.57.23.mov.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566871/80c7b5e2-fea2-c5b6-e5e8-09e0af4c518f.gif)


# 考え方
開始、終了フォームを１度だけしか押せない仕組みを目指します。
具体的には、タスクの開始時刻のデータが入っている場合は開始ボタンを表示しないように、ビューの中にif文を書きます。
この考えに至った経緯は、以下の通りです。

・タスク(Task)に、開始時刻（StartTime）と終了時刻（StopTime）を紐付ける
　→問題点：何回でも開始し、終了できてしまう。
・StartTimeのデータが入っている時（開始している時）、ボタンを表示させないようにする。
・StopTimeも上と同様にする。


# 準備
ターミナル

```
rails new  _6.0.0_ アプリ名 -d mysql
```
```
cd アプリ名
```
```
bundle install
```


# モデルの作成

```
rails g model task
rails g model start_time
rails g model stop_time
```
# モデルの修正
間違いがありましたら、ご指摘お願いします。

```php;task.rb
class Task < ApplicationRecord
  has_one :start_time
  has_one :stop_time
end
```

```php;stop_time.rb
class StopTime < ApplicationRecord
  belongs_to :task
end
```

```php;start_time.rb
class StartTime < ApplicationRecord
  belongs_to :task
end
```


# マイグレーションファイル

```ruby
class CreateTasks < ActiveRecord::Migration[6.0]
  def change
    create_table :tasks do |t|
      t.string :title
      t.timestamps
    end
  end
end
```

```php;202..._create_start_times.rb
class CreateStartTimes < ActiveRecord::Migration[6.0]
  def change
    create_table :start_times do |t|
      t.references :task, foreign_key: true
      t.timestamps
    end
  end
end
```

```php;202..._create_stop_times.rb
class CreateStopTimes < ActiveRecord::Migration[6.0]
  def change
    create_table :stop_times do |t|
      t.references :task, foreign_key: true
      t.timestamps
    end
  end
end
```

ターミナル

```
rails db:create
```
```
rails db:migrate
```

# ルーティング

```ruby
Rails.application.routes.draw do
  root "tasks#index"
  resources :tasks, only: [:index, :create] do
    resources :start_times, only: :create
    resources :stop_times, only: :create
  end 
end
```
使うものしか指定していません。
また、今回は、ネストしていますが、実はしなくても作れます。


# コントローラー
ターミナル

```
rails g controller tasks
rails g controller start_times
rails g controller stop_times
```


```php;start_times_controller.rb
class StartTimesController < ApplicationController
  def create
    StartTime.create(start_time_params)
    redirect_to root_path
  end

  private
  def start_time_params
    params.permit(:task_id)
  end
end
```
```php;stop_times_controller.rb
class StopTimesController < ApplicationController
  def create
    StopTime.create(stop_time_params)
    redirect_to root_path
  end

  private
  def stop_time_params
    params.permit(:task_id)
  end
end
```
```php;tasks_controller.rb
class TasksController < ApplicationController
  def index
    @tasks = Task.all
  end

  def create
    task = Task.create(task_params)
    redirect_to root_path
  end

  private
  def task_params
    params.permit(:title)
  end
end
```
# ビュー
urlは、rails routesで確かめて記入してください。

```php;views/tasks/index.html.haml
-# タスク保存フォーム
= form_with url: tasks_path, method: :post do |f|
  = f.text_field :title
  = f.submit "send"

-# タスク一覧表示
- @tasks.each do |task|
  %br
  タイトル
  = task.title

  -# 時間を確認したい場合は記載してください。
  - if task.start_time != nil
    %br
    開始時刻
    = task.start_time.created_at
    %br
  - if task.stop_time != nil
    終了時刻
    = task.stop_time.created_at
    %br
    %br
  -#　ここまで

  - if task.start_time == nil
    = form_with url: task_start_times_path(task_id: task.id), method: :post do |f|
      = f.submit "開始"
      %br

  - if task.start_time != nil && task.stop_time == nil 
    = form_with url: task_stop_times_path(task_id: task.id), method: :post do |f|
      = f.submit "終了"
      %br
```
今回は、new.html.hamlを全く作っていません。
しかしform_withで、createアクションに対応するurlを指定し、method: :postをつけることで直接保存できるようになります。
うまくいかない場合は、binding.pryなどを使い、送っている値、受け取っている値を確認すると良いと思います。

# まとめ
力技で作った感じがするので、もっと良い方法がある場合は、ぜひコメントしてください！