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のベテランプログラマーによる磨き抜かれた洞察や知恵を結晶したメールマガジンを配信いたします。
私たちは皆さんのメールボックスにスパムを決して送信することのないよう最大限に配慮しています。フォームを送信いただくと確認メールが届きます。
概要
元サイトの許諾を得て翻訳・公開いたします。
日本語タイトルは内容に即したものにしました。