CRUD操作を備えたシンプルな「タスク管理アプリケーション」をscaffordを使わずにゼロから作成.
■ Railsアプリケーション構築のために以下実施.
ビュー層を効率良く書くためにSlim導入.
アプリケーションの見栄えを良くするためにBootstrap導入.
Railsのエラーメッセージなどを日本語で表示出来るよう設定.
■ 作りたい機能は以下5つの機能.
一覧表示機能(タスクの概要を確認できる一覧画面表示)
詳細表示機能(各タスクの全内容を確認できる詳細画面表示)
新規登録機能(新しいタスクのデータをフォーム画面で入力し、データベースへ登録)
編集機能(登録済みタスクのデータをフォーム画面で修正、データベースへ更新)
削除機能(登録済みのタスクをデータベースから削除)
■ 環境構築.
RubyとRailsが導入されていない場合はこちらで導入.
railsプロジェクト作成.
$ rails new taskleaf -d postgresql
$ cd taskleaf
データベース作成.
$ brew services start postgresql
$ bin/rails db:create
gem追加(slim + bootstrap).
gem 'slim-rails' # Slimのジェネレーター
gem 'html2slim' # ERB → SLIMへの変換
gem 'bootstrap' # Bootstrapモジュール
# Gemfileへの追記が完了したらコマンド実行.
$ bundle
既存のERBファイルをSlimファイルへ変換.
$ bundle exec erb2slim app/views/layouts/ --delete
既存のapplication.cssを削除し、scssファイル上でBootstrap呼び出し.
$ rm app/assets/stylesheets/application.css
$ touch app/assets/stylesheets/application.scss
# application.scssに追記
@import "bootstrap";
日本語翻訳対応.
# 日本語翻訳ファイルのインストール.
$ wget https://raw.githubusercontent.com/svenfuchs/rails-i18n/master/rails/locale/ja.yml --output-file=config/locales/ja.ymls
locale.rb作成後、以下を追記.
Rails.application.config.i18n.default_locale = :ja
■ RailsのMVC.
RailsコマンドでModel作成.
# [構文] bin/rails g model [モデル名] [属性名:データ型 属性名:データ型...] [オプション]
$ bin/rails g model Task name:string description:text
■ Railsのモデルは以下2つの要素から構成.
モデルに対応するRubyのクラス.
モデルに対応するデータベースのテーブル.
■ モデルクラスはデータベースのテーブルに以下の命名規約がある.
データベースのテーブル名はクラス名を複数形にしたもの.
モデルのクラスはキャメルケース、テーブル名はスネークケース.
class Task < ApplicationRecord
end
親クラスのActiveRecord::Baseがテーブル構造に対応した属性の読み書きやDB操作を提供.
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
end
モデル作成時に作られたdbファイル(db/migrate/XXXXXX_create_tasks.rb)を実行.
$ bin/rails db:migrate
RailsコマンドでControllerとアクションメソッドを定義.
# [構文] bin/rails g controller コントローラ名 [アクション名 アクション名...] [オプション]]
$ bin/rails g controller tasks index show new edit
設定を以下のように修正.
Rails.application.routes.draw do
root to: 'tasks#index' # デフォルトアクセスの設定
resources :tasks # ルーティングの一括管理
end
■ 新規登録機能.
新規画面へ遷移するためのリンク追加.
h1 タスク一覧
// new_task_pathはURLヘルパーメソッド(URL文字列が生成される)
= link_to '新規登録', new_task_path, class: 'btn btn-primary'
モデルの翻訳機能追記.
models:
task: タスク
attributes:
task:
id: ID
name: 名称
description: 詳しい説明
created_at: 登録日時
updated_at: 更新日時
新規登録画面のアクションメソッド実装.
# コントローラ内の変数をビューから見ることが可能.
# アクションからビューへ受け渡しをしたいデータをインスタンス変数に入れるのが基本的な役割.
# ブラウザに返す画面を省略すると、アクションに対応する画面(app/views/コントローラ名/アクション名.html.slim)が表示.
def new
# 新規のタスクオブジェクト生成.
@task = Task.new
end
新規登録画面のビューを実装.
h1 タスクの新規登録
.nav.justify-content-end
= link_to '一覧', tasks_path, class: 'nav-link'
// { task: @task }でインスタンス変数@taskをパーシャル内のローカル変数taskに渡せる.
= render partial: 'form', locals: { task: @task }
一部処理を共通化(パーシャルテンプレートは先頭にアンダースコア付与).
= 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 nil, class: 'btn btn-primary'
登録アクションの実装.
def create
task = Task.new(task_params)
task.save!
redirect_to tasks_url, notice: "タスク#{task.name}を登録しました。"
end
private
# [Strong Parameters]
# リクエストパラメータから指定の値のみ(name、description)を取得している.
def task_params
params.require(:task).permit(:name, :description)
end
noticeのflashメッセージが存在する場合は画面上に表示.
.container
- if flash.notice.present?
.alert.alert-success = flash.notice
= yield
■ 一覧表示機能.
一覧表示アクションでタスクデータ取得.
class TasksController < ApplicationController
def index
# データベースに保存されている全てのタスクデータを取得.
@tasks = Task.all
end
end
一覧画面で全てのタスクデータを表示.
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(:create_at)
th
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'
■ 詳細表示機能.
指定タスクの詳細情報を取得する実装を追記.
def show
@task = Task.find(params[:id])
end
詳細画面にタスクの属性情報を表示.
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)
// simple_formatはデフォルトでエリアを<p>で囲い、テキストに含まれる一部のHTMLタグを除去.
// 全てのタグを除去するために、hメソッドで<などを<などに変換.
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(task), class: 'btn btn-primary mr-3'
詳細画面上にも[編集]リンクを追加.
= link_to '編集', edit_task_path, class: 'btn btn-primary mr-3'
編集画面上で取得データを表示させるeditアクションとupdateアクション実装.
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
編集画面のビューを以下のように実装.
h1 タスクの編集
.nav.justify-content-end
= link_to '一覧', tasks_path, class: 'nav-link'
= render partial: 'form', locals: { task: @task }
■ 削除機能.
一覧画面上に[削除]リンクを追加.
= link_to '削除', task, method: :delete, data: { confirm: "タスク「#{task.name}」を削除します。よろしいですか?" }, class: 'btn btn-danger'
詳細画面上に[削除]リンクを追加.
= link_to '削除', @task, method: :delete, data: { confirm: "タスク「#{@task.name}」を削除します。よろしいですか?" }, class: 'btn btn-danger'
データ削除のためのアクション実装.
def destroy
task = Task.find(params[:id])
# パラメータ経由で対象タスクのidを受け取り、Taskオブジェクト取得後、対象データをデータベースから削除.
task.destroy
redirect_to tasks_url, notice: "タスク「#{task.name}」を削除しました。"
end
■ 参考文献.
現場で使える Ruby on Rails 5速習実践ガイド.