Ruby on Railsで簡単なアプリを作成

##はじめに
以下の記事を参考に、手を動かしながら簡単なTODOアプリを作成する過程を記録していきます。
[Ruby on Railsで簡単なToDoアプリを作ってみる - Reasonable Code](https://reasonable-code.com/rails-todo/)
##基盤の作成
###プロジェクトを作成する
```
$ rails new todo-app
```
なぜか勝手にgitでの管理が始まりました。まあ別に不都合はないので、コミットしておきます。

```
$ git add .
$ git commit
```

###サーバーを起動する
```
$ rails s
```

###Modelを作成する
RailsではModelを使ってデータベースとやりとりします。基本的にSQL文は書きません。
Model名は頭文字が大文字で、常に単数形です。
デフォルトで「id、created_at、updated_at」の3つのカラムが作られ、ここではさらにstring型のtitleというカラムを追加します。

```
$ rails g model Task title:string
$ rails db:migrate
```
migrationを実行するとデータベースにテーブルが作成されます。現在のデータベースの構造は`/db/schema.rb`というファイルで確認できます。
###Controllerを作成する
indexという（タスク一覧を表示する）アクションをもつtasks_controllerを作成します。
Controller名は頭文字が大文字で、常に複数形です。

```
$ rails g controller Tasks index
```
作成されたControllerに、登録されている全てのタスクを取得するプログラムを記述します。
`Task.all`でtasksテーブルの全てのレコードを取得することができます。

```/app/controllers/tasks_controller.rb
class TasksController < ApplicationController
  def index
    @tasks = Task.all
  end
end
```

###Viewを作成する
Controller内のアクションが実行されると、最後の処理が終わった後に、対応するViewファイルが呼び出されます。
tasks_controllerのindexアクションの場合、対応するViewファイルは`/app/views/tasks/index.html.erb`です。
（まず`/app/views/application.html.erb`が呼び出され、このファイルから対応するViewファイルが呼び出されます。）

```erb:/app/views/tasks/index.html.erb
<h1>タスク一覧</h1>
<table>
  <thead>
    <tr>
      <th>タスク名</th>
    </tr>
  </thead>
  <tbody>
    <% @tasks.each do |task| %>
      <tr>
        <td><%= task.title %></td>
      </tr>
    <% end %>
  </tbody>
</table>
```

###ルーティングを設定する
**どのURL**に対する***どんなリクエスト***を受けた時に、**どのコントローラー**の**どのアクション**を実行するか、を設定します。
1つ1つ手動で設定することもできますが、`resources :{Controller名}`とすると、よく使うルーティングを一括で設定することができます。Railsの魔法の1つです。
また`/`(root)にアクセスされた時に、tasks_controllerのindexアクションが走るように設定しています。

```/config/routes.rb
Rails.application.routes.draw do
  root 'tasks#index'
  resources :tasks
end
```
現在設定されているルーティングの一覧は`rails routes`で確認することができます。

```terminal
$ rails routes
Prefix Verb   URI Pattern               Controller#Action
     root GET    /                         tasks#index
    tasks GET    /tasks(.:format)          tasks#index
          POST   /tasks(.:format)          tasks#create
 new_task GET    /tasks/new(.:format)      tasks#new
edit_task GET    /tasks/:id/edit(.:format) tasks#edit
     task GET    /tasks/:id(.:format)      tasks#show
          PATCH  /tasks/:id(.:format)      tasks#update
          PUT    /tasks/:id(.:format)      tasks#update
          DELETE /tasks/:id(.:format)      tasks#destroy
```

##タスク追加機能
###newアクションを追加
`/tasks/new`に`GET`リクエストがあった時、タスク追加画面を表示するためのnewアクションを作成します。

```/app/controllers/tasks_controller.rb
class TasksController < ApplicationController
  def index
    @tasks = Task.all
  end

  def new
    @task = Task.new
  end
end
```
フォームを表示するために`@task = Task.new`でTaskのモデルオブジェクトを作成しています。
次に、タスク追加画面のviewファイルを作成します。

```erb:/app/views/tasks/new.html.erb
<h1>新規タスク</h1>
<%= form_for(@task) do |f| %>
  <div><%= f.label :title %></div>       #title（タスク）の項目名
  <div><%= f.text_field :title %></div>  #title（タスク）の入力エリア
  <div><%= f.submit %></div>             #送信ボタン
<% end %>
<%= link_to '戻る', tasks_path %>
```
`.erb`ファイルでは、`<% %>`で囲んだ枠の中でRubyのコードを実行することができます。
画面への出力が伴う場合には`<%= %>`を使います。

**form_for**は「フォーム作成→受け取ったデータをテーブルに保存」の流れを簡単に実装することのできるヘルパーメソッドです。
基本的な使い方は以下のようになります。

formを作成：`<%= form_for(@{モデルオブジェクト} do |f|) %> `
labelを作成：`<%= f.label :{カラム名} %>`
input type="text"を作成`：<%= f.text_field :{カラム名} %>`
input type="submit"を作成：`<%= f.submit %>`

###createアクションを追加
`/tasks`に`POST`リクエストがあった時、タスクの追加処理を行うcreateアクションを作成します。

```/app/controllers/tasks_controller.rb
class TasksController < ApplicationController
・
・
・
  def new
    @task = Task.new
  end

  def create
    @task = Task.create(task_params)
    redirect_to tasks_path
  end

  private
    def task_params
      params.require(:task).permit(:title)
    end
end
```
POSTで送信されたパラメーターをデータベースに登録し、最後にタスク一覧画面に遷移させています。よって専用のviewファイルは不要です。また`tasks_path`は`/tasks/`という意味です。（indexアクションが呼び出されます。`rails routes`の`Prefix`を参照）

`private`以下の部分は、`StrongParameters`と呼ばれる仕組みです。Taskモデルのtitleパラメーターが渡ってきた場合のみ、タスク追加処理が走るように制御しています。この仕組みが無いとRailsさんにエラーを出されてしまいます。

###タスク一覧画面にリンクを追加
```erb:/app/views/tasks/index.html.erb
<h1>タスク一覧</h1>
・
・
・
</table>
<%= link_to '追加', new_task_path %> #この行を追加
```
`<%= link_to {表示する文字列}, {リンク先のパス} %>`でhtmlのaタグを作成しています。

##タスク編集機能
###editアクションを追加
`/tasks/{id}/edit`に`GET`リクエストがあった時、タスク編集画面を表示するeditアクションを追加します。
`{id}`はTasksテーブル各レコードのidを指します。

```/app/controllers/tasks_controllers.rb
class TasksController < ApplicationController
  ・
  ・
  ・
  def edit
    @task = Task.find(params[:id])
  end

  private
    def task_params
  ・ 
  ・
end
```
リクエストURL内`{id}`部分の数値を`params[:id]`で取り出しています。
続いて、タスク編集画面のviewファイルを作成します。

```erb:/app/views/tasks/edit.html.erb
<h1>タスク編集</h1>
<%= form_for(@task) do |f| %>
  <div><%= f.label :title %></div>
  <div><%= f.text_field :title %></div>
  <div><%= f.submit %></div>
<% end %>
<%= link_to '戻る', tasks_path %>
```
###updateアクションを追加
`/tasks/{id}`に`POST`or`PUT`or`PATCH`リクエストがあった時、データベースの内容を更新するupdateアクションを作成します。

```/app/controllers/tasks_cotroller.rb
class TasksController < ApplicationController
  ・
  ・
  ・
  def edit
    @task = Task.find(params[:id])
  end

  def update
    @task = Task.find(params[:id])
    @task.update(task_params)
    redirect_to tasks_url
  end
  ・
  ・
end
```
タスク編集画面から送信された内容を受け取り、データベースを更新します。
タスクの編集後、タスク一覧画面にリダイレクトするので、updateアクションのためのviewファイルは不要です。

###タスク一覧画面にリンクを追加
```erb:/app/views/tasks/index.html.erb
<h1>タスク一覧</h1>
・
・
・
    <% @tasks.each do |task| %>
      <tr>
        <td><%= task.title %></td>
        <td><%= link_to '編集', edit_task_path(task) %></td> #この行を追加
      </tr>
    <% end %>
・
・
・
```

##タスク削除機能
###destroyアクションを追加
`/tasks/{id}`に`DELETE`リクエストがあった時、idに対応するレコードをデータベースから削除するdestroyアクションを追加します。destoryというスペルミスに注意。

``` /app/controllers/tasks_controller.rb
class TasksController < ApplicationController
・
・
・
  def destroy
    @task = Task.find(params[:id])
    @task.destroy
    redirect_to tasks_url
  end

  private
    def task_params
・
・
・
```
updateアクションと同様、最後にタスク一覧画面にリダイレクトするので、専用のviewファイルは不要です。

###タスク一覧画面にリンクを追加
```erb:/app/views/tasks/index.html.erb

<h1>タスク一覧</h1>
<table>
・
・
・
    <% @tasks.each do |task| %>
      <tr>
        <td><%= task.title %></td>
        <td><%= link_to '編集', edit_task_path(task) %></td>
        <td><%= link_to '削除', task_path(task), method: :delete %></td>
      </tr>
    <% end %>
・
・
・
```
`<%= link_to %>`で作成されるフォームは、デフォルトでPOSTメソッドのリクエストを送信します。
destroyアクションを実行するには、DELETEメソッドのリクエストを送信する必要があるため、`<%= link_to %>`の第３引数に`method: delete`を指定しています。

##参考
・[Ruby on Railsで簡単なToDoアプリを作ってみる - Reasonable Code](https://reasonable-code.com/rails-todo/)
・[【Rails】form_forの使い方](https://qiita.com/jumpyoshim/items/ee5af466ef7959567174)