This post is Private. Only a writer or those who know its URL can access this post.

Article information
Show article in Markdown
Report article
Help us understand the problem. What is going on with this article?

Ruby on RailsでCRUD操作が出来るタスク管理アプリケーション構築 Part1

CRUD操作を備えたシンプルな「タスク管理アプリケーション」をscaffordを使わずにゼロから作成.

■ Railsアプリケーション構築のために以下実施.

:small_blue_diamond: ビュー層を効率良く書くためにSlim導入.
:small_blue_diamond: アプリケーションの見栄えを良くするためにBootstrap導入.
:small_blue_diamond: Railsのエラーメッセージなどを日本語で表示出来るよう設定.

■ 作りたい機能は以下5つの機能.

:small_blue_diamond: 一覧表示機能(タスクの概要を確認できる一覧画面表示)
:small_blue_diamond: 詳細表示機能(各タスクの全内容を確認できる詳細画面表示)
:small_blue_diamond: 新規登録機能(新しいタスクのデータをフォーム画面で入力し、データベースへ登録)
:small_blue_diamond: 編集機能(登録済みタスクのデータをフォーム画面で修正、データベースへ更新)
:small_blue_diamond: 削除機能(登録済みのタスクをデータベースから削除)

■ 環境構築.

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作成後、以下を追記.

config/initializers/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つの要素から構成.

:small_blue_diamond: モデルに対応するRubyのクラス.
:small_blue_diamond: モデルに対応するデータベースのテーブル.

■ モデルクラスはデータベースのテーブルに以下の命名規約がある.

:small_blue_diamond: データベースのテーブル名はクラス名を複数形にしたもの.
:small_blue_diamond: モデルのクラスはキャメルケース、テーブル名はスネークケース.

app/models/task.rb
class Task < ApplicationRecord
end

親クラスのActiveRecord::Baseがテーブル構造に対応した属性の読み書きやDB操作を提供.

app/models/application_record.rb
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

設定を以下のように修正.

config/routes.rb
Rails.application.routes.draw do
  root to: 'tasks#index'  # デフォルトアクセスの設定
  resources :tasks        # ルーティングの一括管理
end

■ 新規登録機能.

新規画面へ遷移するためのリンク追加.

app/views/tasks/index.html.slim
h1 タスク一覧
// new_task_pathはURLヘルパーメソッド(URL文字列が生成される)
= link_to '新規登録', new_task_path, class: 'btn btn-primary'

モデルの翻訳機能追記.

config/locales/ja.yml
models:
  task: タスク
attributes:
  task:
    id: ID
    name: 名称
    description: 詳しい説明
    created_at: 登録日時
    updated_at: 更新日時

新規登録画面のアクションメソッド実装.

app/controllers/task_controller.rb
# コントローラ内の変数をビューから見ることが可能.
# アクションからビューへ受け渡しをしたいデータをインスタンス変数に入れるのが基本的な役割.
# ブラウザに返す画面を省略すると、アクションに対応する画面(app/views/コントローラ名/アクション名.html.slim)が表示.
def new
  # 新規のタスクオブジェクト生成.
  @task = Task.new
end

新規登録画面のビューを実装.

app/views/tasks/new.html.slim
h1 タスクの新規登録

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

// { task: @task }でインスタンス変数@taskをパーシャル内のローカル変数taskに渡せる.
= render partial: 'form', locals: { task: @task }

一部処理を共通化(パーシャルテンプレートは先頭にアンダースコア付与).

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 nil, class: 'btn btn-primary'

登録アクションの実装.

app/controllers/tasks_controller.rb
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メッセージが存在する場合は画面上に表示.

views/layouts/application.html.slim
.container
  - if flash.notice.present?
    .alert.alert-success = flash.notice
  = yield

■ 一覧表示機能.

一覧表示アクションでタスクデータ取得.

app/controllers/tasks_controller.rb
class TasksController < ApplicationController
  def index
    # データベースに保存されている全てのタスクデータを取得.
    @tasks = Task.all
  end
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(: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'

■ 詳細表示機能.

指定タスクの詳細情報を取得する実装を追記.

app/controller/tasks_controller.rb
def show
  @task = Task.find(params[:id])
end

詳細画面にタスクの属性情報を表示.

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)
      // simple_formatはデフォルトでエリアを<p>で囲い、テキストに含まれる一部のHTMLタグを除去.
      // 全てのタグを除去するために、hメソッドで<などを&lt;などに変換.
      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

■ 編集機能.

一覧画面上に[編集]リンクを追加.

app/views/tasks/index.html.slim
= link_to '編集', edit_task_path(task), class: 'btn btn-primary mr-3'

詳細画面上にも[編集]リンクを追加.

app/views/tasks/show.html.slim
= link_to '編集', edit_task_path, class: 'btn btn-primary mr-3'

編集画面上で取得データを表示させる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

編集画面のビューを以下のように実装.

app/views/tasks/new.html.slim
h1 タスクの編集

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

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

■ 削除機能.

一覧画面上に[削除]リンクを追加.

app/views/tasks/index.html.slim
= link_to '削除', task, method: :delete, data: { confirm: "タスク「#{task.name}」を削除します。よろしいですか?" }, class: 'btn btn-danger'

詳細画面上に[削除]リンクを追加.

app/views/tasks/show.html.slim
= link_to '削除', @task, method: :delete, data: { confirm: "タスク「#{@task.name}」を削除します。よろしいですか?" }, class: 'btn btn-danger'

データ削除のためのアクション実装.

app/controllers/tasks_controller.rb
def destroy
  task = Task.find(params[:id])
  # パラメータ経由で対象タスクのidを受け取り、Taskオブジェクト取得後、対象データをデータベースから削除.
  task.destroy
  redirect_to tasks_url, notice: "タスク「#{task.name}」を削除しました。"
end

■ 参考文献.

:books: 現場で使える Ruby on Rails 5速習実践ガイド.

machio77777
プロジェクトマネージャー / 最近はマネージメント業務や、クライアント折衝がメインのため、業務でコードは書きませんが、プライベートで調べたことをメモ書きレベルで投稿しています。
https://tana-labo.tokyo/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした