Rails: TurboとViewComponentを使うときの注意点(翻訳)
私たちのプロジェクトでは、ビューテンプレートのボタンスタイル統一にViewComponentを使っています。たとえば以下のような感じです。
class Forms::Button < ViewComponent::Base
def initialize(type:, text:, options: {}, data: {}, disabled: false)
@type = type
@text = text
@options = options
@data = data
@disabled = disabled
end
def call
case @type
#...
when "link"
link_to(
@options[:href],
data: @data,
class: "#{@options[:text_color]} #{@options[:bg_color]} #{css_styles} app-btn",
) do
tag.p(@text)
end
end
end
指定されたコンポーネントでPOSTリクエストを行うために、link_toのmethodオプションを使うことに決めました。
#...
link_to(
@options[:href],
method: @options[:method] || "GET",
data: @data,
class: "#{@options[:text_color]} #{@options[:bg_color]} #{css_styles} app-btn",
)
#...
これは動きましたが、ひとつ問題がありました。他のコンポーネントのリンクが動かなくなってしまったのです。
link_toでmethodオプションを指定するとHTMLフォームを動的に作成して即座に送信します。これは@rails/ujsを使っていますが、GETフォームがTurbo Streamsのレスポンスと互換性がないことが判明しました。
修正方法は、この:methodオプションを削除し、button_tagを用いて:postリクエストを送信することでした。
さらに申し上げると、Rails 7では@rails/ujsライブラリがデフォルトではなくなりました。また、link_toのmethod属性も非推奨になったので、使ってはいけません。
訳注
本記事ではbutton_tagを用いる形で解決していますが、最新のRailsガイド(v7.0.4)に示されているように、data:とturbo_methodを使えばlink_toでも一応HTTPメソッドを変更できます↓。ただしアクセシビリティの観点から、非GETメソッドはリンクではなくボタンとフォームにするのが望ましいとも書かれています。
<%= link_to "Delete post", post_path(post), data: { turbo_method: "delete" } %>
Rails APIドキュメントlink_toには、method: HTTPメソッド名のシンボル、remote: true、confirm: "確認メッセージ"、:disable_withの4つがRails UJS由来の属性としてRails 7以降は非推奨と書かれています。
お知らせ: 5600人以上のRailsエンジニアが購読しているメールマガジン
元記事末尾のフォームに登録いただくと、Arkencyのベテランプログラマーによる磨き抜かれた洞察や知恵を結晶したメールマガジンを配信いたします。
私たちは皆さんのメールボックスにスパムを決して送信することのないよう最大限に配慮しています。フォームを送信いただくと確認メールが届きます。
概要
元サイトの許諾を得て翻訳・公開いたします。
日本語タイトルは内容に即したものにしました。