Ruby on Rails トップページでenumを使ったカラムの値をボタンひと押しで変える仕組み
どうもかずきです!
今回は
Ruby on Rails トップページでenumを使ったカラムの値をひと押しで変える
という方法を紹介していきます!
以下のURLの動画ような物をサーバー内で作るイメージです
https://i.gyazo.com/8ce083c08b78da97383ba182141bb926.mp4
enumとは?
enum型
プログラム上での状態や種類などの変数を定数定義してくれて、その定義内であれば勝手にデータを割り当ててくれるのでその値を意識しなくても良くなり、重複防止や可読性の向上が期待される機能です
うん、これだと理解しにくいです
例え話で考えていきましょう(カフェのメニュー)
とあるカフェでは
の名前のついた3つのメニューしか取り扱っていないとします(かなり極端ですみません)
そこでお客さんに『ハイボールください』と言われるとします
しかし先ほどの前置き通り、このカフェでは
1番の”コーヒー”
2番の”エスプレッソ”
3番の”ミルクティー”
しか取り扱っていないので当然店員さんは
『申し訳ございません 当店では”ハイボール”というものはお取り扱いしておりません』
という”例外に対する対応”をします
このようにサーバー(店内)で定義したもの以外ではこのようなエラー(例外に対する対応)を吐きます
逆に、お店で新メニューに"ハイボール"を追加した場合は
と定義順にメニュー内に割り振ってくれるので、
次にお客さんが”ハイボール”を注文し他時は
店員さんは『畏まりました ”ハイボール”ですね ○○円になります』
と行った具合に対応(正常なレスポンス)をしてくれるようになります(居酒屋じゃないんだから、この店のコンセプトブレブレじゃん)
Ruby on Railsのenum
Railsで使う場合は、データベースのレコードのカラムの情報をモデルに定義するものです
先ほどのカフェのメニューを例にすると
app/model/cafe.rb
enum menu: { コーヒー: 1 エスプレッソ: 2 ミルクティー: 3 }
みたいな感じですね
二種類の書き方を紹介するとこんな感じ
app/model/hoge.rb
# 何か特定の値で割り振る場合
enum カラム名: { カラムの中身a: 固定値1 カラムの中身b: 固定値2 カラムの中身c: 固定値3 }
# 自動的に割り振る場合
enum カラム名: { カラムの中身a,カラムの中身b, カラムの中身c }
先ほどのカフェの例だと前者になります
本題
冒頭の動画URLで同じものを貼っていますが、今回はトップページにずらっと並んでいるタスク一覧のSTARTボタンを押すとDOING表示になって、これをもう一度押すとSTARTボタンに戻ってくれる動きを作ります
今回はAJAXなどは使わずにボタンを押すとデータ内のカラムの値と表示が変わってくれる仕組みという認識で大丈夫です
まずはこのボタンをリンクにして、そのリンクを押すと見た目とデータの中身が変わるようにしたいので、パスを作ります
ルーティング
config/routes.rb
Rails.application.routes.draw do # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html root 'tasks#index' resources :tasks do patch :change_status # こいつを追加 end end
一応基本的なルートはすでに作っているのでネストして追加してみます
ちなみにこの場合は部分的更新なのでHTTPメソッドはPATCHにします
データベースのカラムの状態確認もしくは修正
db/schema.rb
# 省略
t.integer "status", default: 0, null: false
# 省略
データはtasksテーブルを作っていてその中のカラムの一つにstatusカラムを作っています ここをいじくります
この意味は型をintegerつまり整数列で管理していて、通常状態を0、このカラムの中身が何もない状態はダメですよと行った感じです
テーブル生成時にこのような制約などを設定するのですが、後から変えることも簡単にできます この記事が参考になるかも?
モデル
続いてここでenumを使います
app/model/task.rb
class Task < ApplicationRecord
# 省略
enum status: { START: 0, DOING: 1, COMPLETED: 2 } def change_status! if START? DOING! else START! end end end
アソシエーションとかバリデーションについての記述も開発においては大事ですが今回の内容的に関連性があまりなさそうなので省略しました
タスクの進捗状況ということで、何も手をつけていないデフォルトの状態がSTART(0)ということになり、DOING(1),COMPLETED(2)と定義できました
今回タスク状態を切り替えたいのはSTARTとDOINGなのでchange_status!メソッドを定義して切り替え可能にします
ちなみに『!(感嘆符)』をメソッドにつけることで例外処理を行えるようになります
コントローラ
app/controller/tasks_controller.rb
class TasksController < ApplicationController before_action :task_set, only: [:show, :edit, :update, :destroy, :change_status]
# 省略
def change_status @task.change_status! redirect_to root_path, notice: 'successfully updated.' end # 省略
private def task_set @task = Task.find(params[:task_id]) end def task_params params.require(:task).permit(:name, :text, :limit_date, :status, :level, :priority, :genre_id) end end
トップページなのでroot_pathにリダイレクトさせるように書いています
細かいところは省いていますがこんな感じです
privateメソッドで定義したtask_setですが、特定のidのtaskを持って来る際にparams[:id]だとnilになってしまうのでtask_idにしています
ビュー
app/view/tasks/index.html.haml
マークダウンだとズレが生じるので写真で失礼します
表示する状態を変数としたいのでtask.status
はじめに作ったパスをリンクにしています
メソッドはpatch
if文で分けている理由はSTARTの時とDOINGの時でclass名を変えて、cssで見た目を変えるためです
これに関してはお好みの問題になって来るので割愛します
ひとまずこのような流れで作成することができました!
それでは