1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

最新のRuby on Railsに一人で迫ってみる挑戦Advent Calendar 2023

Day 8

Turboのチュートリアル記事を読んでいる最中の疑問

Posted at

はじめに

本記事は錆びかけたRailsの知識を頑張ってアップデートするアドベントカレンダー8日目です。

今日は、猫Rails様のTurboのチュートリアルでRails7のTurbo Streamを勉強していたときに浮かんだ疑問についてまとめます。

疑問点

Turbo Streamと「○○.js.erb」との違いは?
flash.noticeとflash.notice.nowとの違いは?
指定ページの強制リロードは本当にできる?

Turbo Streamと「○○.js.erb」との違いは?

非同期の実装について、Rails6までは、Railsでbuttonタグやaタグを作ってくれるメソッドbutton_tagやlink_toなどにremote: trueというオプションをつけ、そこからのリクエストを非同期にするという方法がありました。

<%= hoge_path, method: :post, remote: true do %>
  <%= image_tag "path-to-image", alt: "Like" %>
<% end %>

そして、○○.html.erbではなく○○.js.erbというファイルを用意し、これをrender時に指定することで、JavaScriptを実行してDOMを書き換えてしまうという方法です。

○○.js.erb例
document.getElementById('like-btn<%= @hoge.id %>').innerHTML = "<%= j(render partial: 'likes/like', locals: {hoge: @hoge}) %>"

Rubyのインスタンス変数をJavaScriptに渡して整形、それをクライアントに返却するという形ですね。

この方法でも非同期で見た目を更新でき、いい感じのUXを実現できます。

Turbo Streamsを使うメリット

リクエストをきっかけに複数箇所を更新するためのレールがひかれた、ということでしょうか。
JavaScriptを書くことでもさまざまな挙動は実現できますが、特定のやり方が用意されて、同じチームの人がすぐにコンセンサスを取って書けるのはスピードにつながりそうです。

Turbo Frameでどの部分を置き換えるのかを指定できるturbo_frame_tagのように、turbo Streamでもわかりやすい書き方ができるともっと良さそうですね。現状、idをつけているだけなので若干混乱しそうです。

flash.noticeとflash.notice.nowとの違いは?

Turboとはあんまり関係ないのですが、以下の記述がよくわかりませんでした。

Flashは通常だとリダイレクト時に使うのでflash.noticeを使って設定する。でもTurbo Streamsでは今回のリクエストに対してFlashを設定したい。そういう場合には今回のリクエストに対してだけ有効なflash.now.noticeを利用するよ。

そこで、通常のflashとflash.nowとの違いをまとめておきます。

flash

使用場面:
flashは、主にリダイレクトが伴うアクションで使用されます。つまり、ユーザーが現在のページから別のページにリダイレクトされる場合です。

動作:
flashメッセージはリクエスト間で持続し、リダイレクト後のページで表示されます。その後、次のリクエストで消えます。

flash
def update
  if @user.update(user_params)
    flash[:notice] = "プロファイルが更新されました。"
    redirect_to @user
  else
    render :edit
  end
end

flash.now

使用場面:
flash.nowは、リダイレクトを伴わないアクション、つまり現在のリクエストの中で完結するアクションで使用されます。これは、ページの再描画が発生しないAjaxリクエストやTurbo Streamリクエストに特に有効です。

動作:
flash.nowメッセージは、現在のリクエストでのみ有効で、次のリクエストには持続しません。

flash.now
def create
  @comment = Comment.new(comment_params)
  if @comment.save
    flash.now[:notice] = "コメントが追加されました。"
    render turbo_stream: turbo_stream.append('comments', @comment)
  else
    render :new
  end
end

指定ページの強制リロードは本当にできる?

指定ページの強制リロード
🐱 Turboと相性が悪いJavaScriptのライブラリを使う際に、指定のページだけフルリロードさせたい場合があるよ。そんな時は以下のような要素を追加すると、ページを開いた際にwindow.location.reload()を実行させて強制的にフルリロードさせることができるよ。・・・

追加する要素はheadタグの中身でした(以下参照)。

headタグ
<head>
  ...
  <meta name="turbo-visit-control" content="reload">
</head>

Railsではheadタグはapplication.html.erbに含まれており、これは共通のテンプレートなので特定のページのみ追加するのは難しいのでは?と思いました。

解決策

結論、content_forメソッドを利用することで実現可能でした。

application.html.erbでheadタグの中身にyieldを追加します。

<!-- application.html.erb -->
<head>
  ...
  <%= yield :head %>
</head>

その後任意のビューでcontent_forを使って、必要なmetaタグを追加できます。

<!-- 例えば、特定のビューのファイル -->
<% content_for :head do %>
  <meta name="turbo-visit-control" content="reload">
<% end %>

このコードは、そのビューがレンダリングされるときにのみmetaタグがheadセクションに挿入されます。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?