はじめに
本記事は錆びかけたRailsの知識を頑張ってアップデートするアドベントカレンダー23日目です。
今回は、Rails7.1から使えるようになった例外(エラー通知)について紹介します。
この機能もすごくRailsらしい機能だな、と思ったのでそこから考えたことを軽く書きました。
ErrorReporterについて
Rubyでのこれまでの例外処理といえば、以下のように書くのでした。
begin
// エラーが発生するかもしれないなんらかの処理
rescue SomethingIsBroken => error
MyErrorReportingService.notify(error)
end
これが、Rails7.1からは、以下のように書けるということです。
Rails.error.handle(SomethingIsBroken) do
// エラーが発生するかもしれないなんらかの処理
end
MyErrorReportingService.notify(error)
はどこに行ったのかというと、以下のようにinitializerの処理として書いておけます。
class ErrorSubscriber
def report(error, handled:, severity:, context:, source: nil)
MyErrorReportingService.report_error(error, context: context, handled: handled, level: severity)
end
end
ErrorReporterの詳細については、Railsガイドの該当ページをご覧ください。
Rails(など)における省略記法のトレードオフ
今回のErrorReporterの導入は、直感的に「例外処理がスッキリわかりやすくなったな」と感じました。これまでコードの各所に書いてあったMyErrorReportingService.notify(error)
みたいな通知の記述を共通化できるためです。
一方で、パッとコードを見た人は何をやっているのかわからないでしょう。
Railsの良いところでもあり悪いところでもある(というかトレードオフ)、省略記法に似たにおいを感じたのです。
<%= render @cats %>
<div>
<p><%= cat.name %></p>
<!-- 他の猫の詳細情報を表示する -->
</div>
初見の人は、「一体何が起きているんだ・・・?!」となるでしょう。
このindex.html.erbを省略せずに書くと以下のようになります。
<%= render partial: 'cat', collection: @cats, as: :cat %>
まだわかりづらいところもありますが、partial
で部分テンプレートを指定し、collection
で配列を渡して、as
で部分テンプレート内の変数を決めている、と言われれば納得できる人も出てくるでしょう。
さらにわかりやすくするなら、@cats
コレクションを繰り返し、逐一catをレンダリングするようにもできます。
<% @cats.each do |cat| %>
<%= render 'cat', cat: cat %>
<% end %>
このような説明を経て、ようやく最初の<%= render @cats %>
というシンプルな表記にたどり着けます。
このように、省略記法は短く書けて生産性が上がる代わりに初見の人にとってわかりづらい(学習コストが高い)というトレードオフがあります。
どのように対応するか
チームに招けるメンバーのレベルや教育の質を鑑み、先を見越してコーディングの方針を決めておく必要があります。
Rails7系から活発に使われるようになってきているhotWireでも同じような省略記法が使えますね。
わかりづらいからという理由で省略記法を敬遠するとなるとコード量が増えます。基本的には、さまざまな場面で生まれるこのような記法の揺れが起こらないよう、ガイドラインを作るべきです。