【Rails】TECH::EXPERT【75日目】

【学習内容】


・タスク管理アプリの作成 後半

【タスク管理アプリの作成 後半】

(1)コントローラーとビュー作成

コントローラー名だけ決めれば、テキストエディタからでも内容の記述はできますが、効率的に雛形をつくるには、アクションについて現段階から考慮する必要があります。

$bin/rails g controller tasks index show new edit

このようにあらかじめ4つのアクションを定義しておきます。

(2)ルーティングの編集

(1)の方法でコントローラーを作成すると、個別にルーティングが記載されるのですが、後ほどresoursesを使用してルーティングを設定するので、下記の記述は削除します。

get ‘tasks/index’
get ‘tasks/show’
get ‘tasks/newget ‘tasks/edit’

その代わりにresourcesメソッドを使用して各アクションに関するルーティングを定義します。ついでに、rootのページをindexの画面に遷移するようにしておきます。

■route.rb

Rails.application.routes.draw do
root to: ‘tasks#indexresources :tasks
end


(3)一覧画面に新規登録リンクを追加

■app/views/tasks/index.html.slim

h1 タスク一覧
= link_to ‘新規登録’ , new_task_path, class: ‘btn btn-primary’

(4)モデルの翻訳情報を追加する

■config/locales/ja.yml

ja:
activerecord:
  errors:
    messages:
      record_invalid: “バリデーションに失敗しました: %{errors}restrict_dependent_destroy:
        has_one:%{record}が存在しているので削除できません”
        has_many:%{record}が存在しているので削除できません”
  models:
    task: タスク
  attributes:
    task:
    id: ID
    name: 名称
    description: 詳しい説明
    created_at: 登録日時
    updated_at: 更新日時

(5)新規登録画面のためのアクションを実装する

アクションからビューに受け渡すデータをインスタンス変数に代入します。

■app/controllers/tasks_controller.rb

def new
@task = Task.new
end


(6)新規登録画面のビューを実装する

フォームの内部には、bootstrapで用意されている「.form-group」というクラスを利用してスタイリッシュな感じにします。

■app/view/tasks/new.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, row: 5, class: ‘form-control’, id: ‘task_description
= f.submit nil, class: ‘btn btn-primary

(7)登録アクションを実装する

フォームに記入したデータを保存するにはcreateアクションを定義すればOKです。
Strong_parametersとして安全にデータの受渡をおこないます。

■app/controller/tasks_controller.rb

def create
task = Task.new(task_params)
 task.save!
 redirect_to tasks_url, notice: ‘タスク「#{task.name}」を登録しました’
end

private
def task_params
 params.require(:task).permit(:name, :description)
end

privateメソッド以下には、ストロングパラメーターを設定し、「:name」「:description」以外のデータはparamsに格納しないようにします。

createアクションでは、ストロングパラメーターによってチェックされたデータを受け取り、新しいカラムを作成します。

保存をしたあとは、一覧画面に遷移させると同時に、noticeでフラッシュメッセージを表示させます。(flash[:notice]という形でタスク登録完了のメッセージをセットしてからリダイレクトしているということです)

■app/views/layouts/application.html.slim

.container
 -if flash.notice.present?
.alert.alert-success= flash.notice
 = yield

view共通部分のapplication.html.slimに上記コードを追記することで、controllerで記載したnoticeが表示されるようになりました。

ちなみに、ページの更新を実行するとnoticeは消えます。

(8)登録したタスクを一覧表示する

■app/controllers/task_controllers,rb

def index
@tasks = Task.all
end

■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)
 tbody
   - @tasks.each do |task|
     tr
       td = task.name
       td = task.created_at

controllerで定義した@tasksをeach文で回して1つずつ表示させます。
tableに関しては、trで項目名を設定し、tbody部分でeachの結果を表示させます。

(9)タスクの詳細を確認できるようにする

■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)
 tbody
   - @tasks.each do |task|
     tr
       td = link_to task.name, task_path(task)
       td = task.created_at

ヘルパーメソッドを使って、該当のtaskの詳細に飛べるリンクを作成しました。

引数で(task)を渡すことによって、URLでは「tasks/[タスクのID]」という証左表示のためのURLに飛べます。

■app/controllers/task_controllers.rb

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

findメソッドを使用して、詳細画面を表示するためのtaskオブジェクトを生成しIDを引数としてparams[:id]を渡します。

■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
td = simple_format(h(@task.description), {}, sanitize: false, wrapper_tag: “div”)

について、simple_formatはヘルパーメソッドの1つで、デフォルトでエリアをpタグで囲い、テキストに含まれる一部の危険なHTMLタグを取り除いてくれます。(sanitizeオプション)。また今回はwrapper_tagを使用し、本体のpタグからdivタグで囲うようにしています。

(10)編集機能の実装

■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 = task.name
       td = task.created_at
       td
         = link_to ‘編集’, edit_task_path(task), class: ‘btn btn-primary nr-3’

タスク一覧画面の1番右の列に編集ボタンを設置しました。


■app/views/tasks/show.html.slim

Table.table-hover
・
・
・
tr
     th- Task.human_attribute_name(:created_at)
     td = @task.created_at
tr
     th- Task.human_attribute_name(:created_at)
     td = @task.updated_at
=link_to ‘編集’, edit_task_path, class: ‘btn btn-primary nr-3’

タスク詳細ページも同様に編集ボタンを設置します。


■app/contoroller/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

@taskの取得方法は、newのときとほぼ一緒ですね。

■app/view/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, row: 5, class: ‘form-control’, id: ‘task_description
= f.submit nil, class: ‘btn btn-primary

(11)partialを使った切り出し

(10)の作業を通じて、new.html.slim とedit.html.slimの画面は全く同じ入力フォームを使用していることがわかります。

このように同じような記述がある場合は、重複している部分を切り出して、共通化します。

その際に用いるのが、partialテンプレートです。

共通化する部分のコードは「_(アンダースコア)」から始まるファイルに移管します。

■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, row: 5, class: ‘form-control’, id: ‘task_description
= f.submit nil, class: ‘btn btn-primary

この部分をnew.html.slim とedit.html.slimから呼び出すことで、今までと違いなく使用することができます。

■app/view/tasks/new.html.slim

h1 タスクの編集
.nav.justify-content-end
= link_to ‘一覧’ , tasks_path, class: ‘nav-link
= render partial: ‘form’, locals: {task: @task}

■app/view/tasks/edit.html.slim

h1 タスクの編集
.nav.justify-content-end
= link_to ‘一覧’ , tasks_path, class: ‘nav-link
= render partial: ‘form’, locals: {task: @task}

localsオプションは、パーシャル内のローカル変数を定義します。
ここでは「インスタンス変数@taskをパーシャル内のローカル変数taskとして渡します」という意味です。

(12)削除機能の追加

■app/view/tasks/index.html.slim

・
・
・
tbody
  - @tasks.each do |task|
    tr
      td = link_to task.name, 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'


■app/views/tasks/show.html.slim

table.table-hover
・
・
・
tr
     th- Task.human_attribute_name(:created_at)
     td = @task.created_at
tr
     th- Task.human_attribute_name(:created_at)
     td = @task.updated_at
=link_to ‘編集’, edit_task_path, class: ‘btn btn-primary nr-3’
= link_to '削除', task, method: :delete, data{ confirm: "タスク「#{task.name}」を削除します。よろしいですか?" }, class: 'btn btn-danger'

■app/controller/tasks_contorller.rb

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








この記事が気に入ったらサポートをしてみませんか?