Ruby on Railsトグル操作
チェクボックスのトグル動作を実装しよう
タスクの完了状態を管理するための
チェックボックスの動作を実装していく!
チェックボックスの状態が変わるたびに
サーバーへデータを送信してデータベースの値を書き換える必要がある。
ページのリロードなしにサーバーとの通信を行うには、
JSを使ったAjaxによる実装を行うことが多い。
Ajaxとは、Asynchronous JavaScript + XMLの略称
Webブラウザ内で非同期通信を行いながら、
インターフェイスの構築を行う手法のこと。
(画面を遷移しなくても、サーバーとの通信を行いながら動的に画面の表示内容が変わるWebアプリが作れる技術)
Rails7から導入されたTurboという仕組みを使うと、
JSを記述しなくてもJSで実装するような動的な動作をさせることができる!
データ送信に関するルーティングの設定
config→routes.rbファイルで次のように記述!
resources :tasks do
member do
patch :toggle
end
end
この行のルーティングを使う!
tasks_controllerにtoggleメソッドを用意する!
destroyメソッドの下に記述!
def toggle
end
チェックボックスの状態の変化に伴い、
データが送信されるとこのメソッドが呼ばれるので
対応する処理をかく!
↓
次にviewsのtasks配下に新規_completed.html.erbファイルを作成
(viewを共通化しておき呼び出すため)
<%= turbo_frame_tag task do %>
<%= form_with model: task, url: toggle_task_path(task) do |f| %>
<li>
<span>
<%= f.check_box :completed,
onchange: 'this.form.requestSubmit()' %>
<%= task.title %>
<%= link_to '[edit]', edit_task_path(task),
data: { turbo_frame: '_top'} %>
<%= link_to '[destroy]', task_path(task),
data: { turbo_method: 'delete',
turbo_confirm: 'Are you sure?'} %>
</span>
</li>
<% end %>
<% end %>
turbo_frame_tagからendで囲った部分がturboで
差し替え可能なdomになる!
taskの部分にはモデルのインスタンスを設定する。
↓
次にチェックボックスのオンオフが発生した時に
サーバーにデータを送信する処理を書く!
(tasks_controlerのtoggleメソッドへデータを送信する処理)
↓
あとでスタイルを当てる時に使うspandでチェックボックスを囲っておく
onchangeの部分でチェックボックスがオンオフされた時に
ボタンを押さなくてもデータがsubmit(送信)される。
チェックボックス以外の要素もindex.html.erbから
partialに移動させておく!(task.titleから下の部分)
index.html.erbでpartialを呼びだす!
<%= render 'completed', task: task %>
taskという名前で変数taskの値をpartialに渡している!
動作確認
- チェックボックスをオンオフした時にターミナルのログを確認してデータが送信されているか。
Parametersに送られてきたParameterが表示されている。
このタスクのIDを元にデータベースから該当のレコードを取得する!
tasks_controllerを開き
toggleメソッドを編集!
def toggle
@task.update(completed: !@task.completed)
render turbo_stream: turbo_stream.replace(
@task,
partial: 'completed',
locals: { task: @task }
)
end
!@task.completedで現在データベースに保存されている値を反転して
データベースの値をupdateする。
↓
現在表示されているdomを動的に書き換え、引数を書いていく。
turbo_stream.replaceでturboを利用してdomの書き換えをする。
replaceメソッドの各引数については
@taskの部分はタスクオブジェクトが自動生成するdomid
例えば、task_3やtask_4などに合致するidのターボフレームを
書き換えするという意味。
partial: 'completed'で置き換えに使用するpartialを指定。
locals: { task: @task }の記述でpartialに渡すパラメーターを指定している。
taskという名前で、@taskの値をpartialに渡す。
動作確認
新規に作成したタスクについて操作!
- チェックボックスをオンオフしてリロード
- DOMの状態をチェック
検証でターボフレームが動的に書き変わっているのが確認できればOK!
完了したタスクに取り消し線を引く引く処理を追加!
_completed.html.erbファイルのspan要素に属性を作成!
<span class="<%= task.completed? ? 'completed' : '' %>">
もし、task.completedがtrueならば、
span要素にclass completedをつける。
もしfalseならばclassはつけない。
動作確認
- 検証でチェックをオンオフした際にspan要素が変更されればOK!
CSSでcompletedクラスを作り、線を引くスタイルを設定する。
app→assets→stylesheetsの中のapplication.cssを開き
一番下に次のように入力!
.completed {
text-decoration: line-through;
}
タスクにチェックを入れたとき(span要素にclass="completed"がつくと)
text-decorationのスタイルがあたり、取り消し線がつく!
チェックを外すとspanの属性の値が空になるので、
スタイルが当たらなくなり取り消し線がつかない。
このように、JSを記述しないで、railsだけで動的なページを作成することができた!
リファクタリングをしよう-コントローラー
tasks_controllerを開き、
editメソッドのTask.findの処理に着目!
@task = Task.find(params[:id])
特定のidのtasksのレコードをデータベースから取得する処理が
edit,update,destory,toggleメソッドに存在するので
共通化する!
task_paramsの下に
def set_task
@task = Task.find(params[:id])
end
class名の下にも記述
before_action :set_task, only: [:edit, :update, :destroy, :toggle]
この記述で各メソッドが実行される前にset_taskメソッドを実行するという意味になる。
共通化した部分を一旦コメントアウトし、動作確認を行う!
動作確認
- 確認用のタスクを新規に作成
- 最後に登録したタスクのeditをクリックして編集画面を表示
- タスク名を変更し、データを更新
- チェックボックスにチェックを入れる、外す、リロード
- destroyを押してデータを削除
動作確認ができたら不要なコメントを削除しておく!
全体を通しての動作確認をしよう
ターミナルを開き、データベースの値をリセットする!
(バリデーション登録前のデータも削除したいので)
rails dm:migrate:reset
データベースの値がリセットされた。
rails s
ページを起動する!
動作確認
- 新規登録で空と5文字以下を試す
- 5文字以上で登録できたら編集!
- また空と5文字以下を試す
- 5文字以上で編集ができるか確認!
- チェックボックスの動作、オンオフ、リロード
- タスクが複数登録できるか
- 削除確認!
一旦一通り1つの講座が終わった!
完璧に理解しているわけじゃないから、
明日からまたもう一度繰り返していって理解を深める!
説明できるくらいになる!
今日学校の申し込みも終わったから
来月からは予習も合わせて頑張る
Discussion