第4回 Ruby on Rails 〜タスク管理アプリケーション CRUD機能の実装②〜

Bootstrap

前回同様、タスク管理アプリケーションに機能を実装します。

今回は詳細機能からの実装になります。

  • ・一覧表示機能
  • ・新規登録機能
  • ・詳細表示機能
  • ・編集機能
  • ・削除機能

詳細機能

詳細機能を実装します。詳細画面からタスクの全ての情報を確認できるようにします。

詳細画面の導線の追加

一覧画面で興味あるタスクをクリックした時に詳細画面に遷移するようにします。

app/views/tasks/index.html.slimを開き、タスク名称部分を以下の通りに変更します。

app/views/tasks/index.html.slim

td= link_to task.name, task_path(task)

これでタスクの名称部分がリンクになり、”tasks/[タスクid]”という詳細表示のURLに遷移するようになりました。

アクションの実装

続いて詳細表示アクションを実装します。

app/controllers/tasks_controller.rbのshowアクションを以下のように変更します。

app/controllers/tasks_controller.rb

def show
  @task = Task.find(params[:id])
end

ここではfindメソッドにより、詳細画面に表示するためのTaskオブジェクトを取得しています。
params[:id]はリクエストパラメータから得られるid、つまり”tasks/[タスクid]”の[タスクid]が格納されています。

取得したオブジェクトは@taskというインスタンス変数に代入されビューに渡されます。

詳細画面にタスク情報の表示

app/views/tasks/show.html.slimを下記のように修正します。

app/views/tasks/show.html.slim

h1 タスクの詳細

.nav.justify-content-end
  = link_to '一覧', tasks_path, class: 'nav-link'
table.table.table-hover
  tbody
    tr
      th= Task.human_attribute_name(:id)
      td= @task.id
    tr
      th= Task.human_attribute_name(:name)
      td= @task.name
    tr
      th= Task.human_attribute_name(:description)
      td= simple_format(h(@task.description), {}, sanitize: false, wrapper_tag: "div")
    tr
      th= Task.human_attribute_name(:created_at)
      td= @task.created_at
    tr
      th= Task.human_attribute_name(:updated_at)
      td= @task.updated_at

タスクの説明部分(description)の表示部分ではsimple_formatを使っています。
simple_formatはデフォルトで文字列を<p>タグで囲み、改行は<br>タグを付与します。

また、sanitizeオプションはfalseにして全てのタグを安全な形で表示します。
wrapper_tagを<div>に指定することで、表示エリアを<div>で囲むことができます。

ここまで実装したら一旦(http://localhost:3000/tasks)にアクセスします。

一覧画面でタスク名称をクリックして詳細画面に遷移できたら成功です。
以上で詳細機能は完成です。

編集機能

次に編集機能を実装します。既存のタスクの属性の値を変更してデータベースに保存します。

編集画面の導線の追加

今回は一覧画面のタスク情報毎に「編集」リンクを表示します。これらのリンクをクリックすると各タスクの編集画面へ遷移できるようにします。

また、詳細画面からも編集画面へ遷移できるように「編集」ボタンを追加します。

編集画面で変更したいフィールドの値を変えて「更新」を押すと、データベースのタスクデータを更新した後、一覧画面へ遷移します。

まずは一覧画面に編集画面のリンクを追加します。

app/views/tasks/index.html.slim

h1 タスク一覧

= link_to '新規登録', new_task_path, class: 'btn btn-primary'

.mb-3
table.table.table-hover
  thead.thead-default
    tr
      th= Task.human_attribute_name(:name)
      th= Task.human_attribute_name(:created_at)
      th
  tbody
    - @tasks.each do |task|
      tr
        td= link_to task.name, task_path(task)
        td= task.created_at
        td
          = link_to '編集', edit_task_path(task), class: 'btn btn-primary mr-3'

一覧画面にアクセスすると編集ボタンが追加されています。

次に詳細画面にも編集画面へのリンクを追加します。

app/views/tasks/show.html.slim

h1 タスクの詳細

.nav.justify-content-end
  = link_to '一覧', tasks_path, class: 'nav-link'
table.table.table-hover
  tbody
    tr
      th= Task.human_attribute_name(:id)
      td= @task.id
    tr
      th= Task.human_attribute_name(:name)
      td= @task.name
    tr
      th= Task.human_attribute_name(:description)
      td= simple_format(h(@task.description), {}, sanitize: false, wrapper_tag: "div")
    tr
      th= Task.human_attribute_name(:created_at)
      td= @task.created_at
    tr
      th= Task.human_attribute_name(:updated_at)
      td= @task.updated_at

= link_to '編集', edit_task_path, class: 'btn btn-primary mr-3'

編集画面にアクセスすると編集ボタンが追加されています。

アクションの実装

編集機能で実装するアクションは、編集画面を表示するeditアクション、送られてきたデータを用いてデータベースを更新するupdateアクションの2つがあります。

app/controllers/tasks_controller.rbのeditアクションとupdateアクションを以下のように修正します。

app/controllers/tasks_controller.rb

def edit
  @task = Task.find(params[:id])
end

def update
  task = Task.find(params[:id])
  task.update!(task_params)
  redirect_to tasks_url, notice: "タスク「#{task.name}」を更新しました。"
end

editアクションでは、リクエストパラメータから得られるidから編集対象のTaskオブジェクトを取得します。それをインスタンス変数に代入して編集画面に渡します。

updateアクションでは、同様にTaskオブジェクトを取得し、update!メソッドでtaskパラメータの代入とデータベースへの保存を行なっています。
最後にFlashメッセージを添えて一覧画面に遷移します。

次にビューを実装します。app/views/tasks/edit.html.slimを以下のように修正します。

app/views/tasks/edit.html.slim

h1 タスクの編集

.nav.justify-content-end
  = link_to '一覧', tasks_path, class: 'nav-link'

= form_with model: @task, local: true do |f|
  .form-group
    = f.label :name
    = f.text_field :name, class: 'form-control', id: 'task_name'
  .form-group
    = f.label :description
    = f.text_area :description, rows: 5, class: 'form-control', id: 'task_description'
  = f.submit '更新する', class: 'btn btn-primary'

修正できたら一覧画面にアクセスして、任意のタスクの編集画面に遷移します。

編集フォームが表示され、現在のデータが表示されます。
名称と説明を変更して更新をクリックします。

上記メッセージが出てタスク名称が更新されれば成功です。

以上で編集機能は完成です。

入力フォームの共通化

これまでに作成したapp/views/tasks/new.html.slimとapp/views/tasks/edit.html.slimファイルを比較すると、入力フォーム部分が同じです。このフォーム部分を共通化してメンテナンスしやすくします。

共通化にはrenderメソッドのパーシャルオプションを使います。

まず、パーシャルテンプレートとしてapp/views/tasks/_form.html.slimファイルを作ります。パーシャルテンプレートのファイル名は先頭に_をつけます。ただしrenderメソッドで呼び出す際は_はつけません。

app/views/tasks/_form.html.slim

= form_with model: @task, local: true do |f|
  .form-group
    = f.label :name
    = f.text_field :name, class: 'form-control', id: 'task_name'
  .form-group
    = f.label :description
    = f.text_area :description, rows: 5, class: 'form-control', id: 'task_description'
  = f.submit '登録する', class: 'btn btn-primary'

その後new.html.slimを以下のように修正します。

app/views/tasks/new.html.slim

h1 タスクの新規登録

.nav.justify-content-end
  = link_to '一覧', tasks_path, class: 'nav-link'

= render partial: 'form', locals: { task: @task }

locals: { task: @task }を記述することでインスタンス変数@taskを、パーシャル内のローカル変数taskとして渡すことができます。

同様にapp/views/tasks/edit.html.slimを修正します。

app/views/tasks/edit.html.slim

h1 タスクの編集

.nav.justify-content-end
  = link_to '一覧', tasks_path, class: 'nav-link'

= render partial: 'form', locals: { task: @task }

以上で入力フォームの共通化ができました。

削除機能

最後に削除機能を実装します。

削除の導線の追加

一覧画面のタスク情報毎に「削除」ボタンを表示します。このボタンをクリックすると、削除確認のダイアログが表示され、OKをクリックするとタスクが削除され一覧画面に遷移するようにします。

また、詳細画面にも削除ボタンを配置します。

一覧画面(app/views/tasks/index.html.slim)を以下のように修正します。

app/views/tasks/index.html.slim

h1 タスク一覧

= link_to '新規登録', new_task_path, class: 'btn btn-primary'

.mb-3
table.table.table-hover
  thead.thead-default
    tr
      th= Task.human_attribute_name(:name)
      th= Task.human_attribute_name(:created_at)
      th
  tbody
    - @tasks.each do |task|
      tr
        td= link_to task.name, task_path(task)
        td= task.created_at
        td
          = link_to '編集', edit_task_path(task), class: 'btn btn-primary mr-3'
          = link_to '削除', task, method: :delete, data: { confirm: "タスク「#{task.name}」を削除します。よろしいですか?" }, class: 'btn btn-danger'

link_toのdataオプションにconfirm: “メッセージ”を渡すとリンクをクリックしたときに確認ダイアログを表示できます。OKが押された場合のみDELETEリクエストを行います。

続いて詳細画面(app/views/tasks/show.html.slim)にも削除ボタンを追加します。

app/views/tasks/show.html.slim

h1 タスクの詳細

.nav.justify-content-end
  = link_to '一覧', tasks_path, class: 'nav-link'
table.table.table-hover
  tbody
    tr
      th= Task.human_attribute_name(:id)
      td= @task.id
    tr
      th= Task.human_attribute_name(:name)
      td= @task.name
    tr
      th= Task.human_attribute_name(:description)
      td= simple_format(h(@task.description), {}, sanitize: false, wrapper_tag: "div")
    tr
      th= Task.human_attribute_name(:created_at)
      td= @task.created_at
    tr
      th= Task.human_attribute_name(:updated_at)
      td= @task.updated_at

= link_to '編集', edit_task_path, class: 'btn btn-primary mr-3'
= link_to '削除', @task, method: :delete, data: { confirm: "タスク「#{@task.name}」を削除します。よろしいですか?" }, class: 'btn btn-danger'

アクションの実装

次にアクションを実装します。

app/controllers/tasks_controller.rbにdestroyアクションを追加します。

app/controllers/tasks_controller.rb

def destroy
  task = Task.find(params[:id])
  task.destroy
  redirect_to tasks_url, notice: "タスク「#{task.name}」を削除しました。"
end

destroyアクションではパラメータ経由で対象タスクのidを受け取り、Taskオブジェクトをデータベースから取得します。destroyメソッドで対象のタスクレコードをデータベースから削除し、Flashメッセージとともに一覧画面に遷移します。

一覧画面を表示し、削除ボタンをクリックします。

ダイアログが表示されたらOKをクリックします。

削除が実行されメッセージが表示されます。削除したタスクが一覧画面に表示されなくなれば成功です。

以上で削除機能は完成です。

終わりに

以上でタスク管理アプリケーションにCRUD機能を実装することができました。

今後もこのタスク管理アプリにテストや検索・ソート、メール認証などの機能を追加していこうと思います。

コメント

タイトルとURLをコピーしました