【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/new’
get ‘tasks/edit’
その代わりにresourcesメソッドを使用して各アクションに関するルーティングを定義します。ついでに、rootのページをindexの画面に遷移するようにしておきます。
■route.rb
Rails.application.routes.draw do
root to: ‘tasks#index’
resources :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
この記事が気に入ったらサポートをしてみませんか?