はじめに
本記事は錆びかけたRailsの知識を頑張ってアップデートするアドベントカレンダー16日目です。
引き続きTurboを学習していて、ふと気になったことがありました。
それは、○○.turbo_stream.erb
ファイルの置き場です。
○○.turbo_stream.erbとは?
Turbo Streamを使って非同期通信を行う際、更新する要素の情報を書いておくファイルです。
例えば、コメント一覧とコメントの総数を非同期で更新したい場合を考えます。
以下のようなコメントを一覧表示しているviewがあるとします。
<!-- app/views/comments/index.html.erb -->
<div id="comments_count">
<%= pluralize(Comment.count, 'comment') %>
</div>
<div id="comments_list">
<%= render @comments %>
</div>
このとき、以下のようにcreate.turbo_stream.erb
というファイルを用意します。
<%= turbo_stream.append "comments_list", partial: "comments/comment", locals: { comment: @comment } %>
<%= turbo_stream.update "comments_count", Comment.count %>
すると、comments_list
およびcomments_count
の値を非同期で更新できるようになる、というものです。
○○.turbo_stream.erbファイルの置き場問題
これを見たとき、create.html.erb
とファイルの置き場所がかぶるので別の場所に置いておけないかと思いました。同様の例にmailerのerbファイルがありますが、あれはどちらか消してしまうのであまり違和感を感じません。
ただその場合、通常のerbファイル(○○.html.erb)はそのままの場所に置いておきたいので、turbo_streamファイルの方だけを別に置く形になりそうです。
○○.turbo_stream.erbファイルの置き場候補
Turbo Streamsのファイルを別のフォルダにまとめて分けたい場合、Railsのビューパスの設定をカスタマイズすることになります。その場合、以下の方法が考えられます。
コントローラーレベルでのパスのカスタマイズ
カスタムレンダラーの作成
コントローラレベルでのビューパスのカスタマイズ
各コントローラで、レスポンスのフォーマットに応じてビューパスをカスタマイズすることができます。例えば、FugasControllerのhogeアクションでTurbo Streamのビューパスを設定するには:
class FugasController < ApplicationController
def hoge
respond_to do |format|
format.turbo_stream { render turbo_stream: "turbo_streams/hoge" }
# 他のフォーマットに対するレスポンスもここに記述
end
end
end
この例では、app/views/turbo_streams/hoge.turbo_stream.erbに対応するビューファイルを使用するように指定しています。
カスタムレンダラーの作成
カスタムレンダラーを作成することで、特定のフォーマット(例えばTurbo Streams)に対して表示するビューを決めるロジックを変更できます。
# lib/custom_turbo_stream_renderer.rb
module CustomTurboStreamRenderer
def render(options = nil, extra_options = {}, &block)
if options.is_a?(Hash) && options[:turbo_stream].present?
options[:template] = "turbo_streams/#{options[:turbo_stream]}"
end
super(options, extra_options, &block)
end
end
### コントローラーでこのモジュールをインクルード
```ruby:コントローラーでの例
class FugasController < ApplicationController
include CustomTurboStreamRenderer
# ...
end
この例では、turbo_streamオプションが指定された場合に、turbo_streamsディレクトリをビューパスとして使用するようにカスタマイズしています。
終わりに
調べてみて感じたのは、これらの手段はあまり使わない方が良い、ということです。
例えば複数のリソースが同じアクションでturbo_streamを利用する場合ファイル名が衝突しますし、Railsの規約から逸脱すると、将来的なメンテナンスやRailsのバージョンアップグレード時に問題が生じる危険もあるためです。
1つ目のやり方であればまだ検討の余地がありそうですが、よほど大量のstreamを使って混乱が生じそうな設計以外では使うメリットよりデメリットの方が大きくなってしまいそうです。