🌽

Ruby on Railsトグル操作

2023/02/19に公開

チェクボックスのトグル動作を実装しよう

タスクの完了状態を管理するための
チェックボックスの動作を実装していく!

チェックボックスの状態が変わるたびに
サーバーへデータを送信してデータベースの値を書き換える必要がある。

ページのリロードなしにサーバーとの通信を行うには、
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