Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

週刊Railsウォッチ: キャッシュシリアライザに`:message_pack`が追加、ViewComponent 3リリースほか(20230530前編)

こんにちは、hachi8833です。

週刊Railsウォッチについて

  • 各記事冒頭には🔗でパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
  • 「つっつきボイス」はRailsウォッチ公開前ドラフトを(鍋のように)社内有志でつっついたときの会話の再構成です👄
  • お気づきの点がありましたら@hachi8833までメンションをいただければ確認・対応いたします🙏

TechRachoではRubyやRailsなどの最新情報記事を平日に公開しています。TechRacho記事をいち早くお読みになりたい方はTwitterにて@techrachoのフォローをお願いします。また、タグやカテゴリごとにRSSフィードを購読することもできます(例:週刊Railsウォッチタグ)

🔗Rails: 先週の改修(Rails公式ニュースより)

🔗 Action Mailboxのジェネレータで主キー設定を反映するようになった

動機/背景
最近、新しいRails 7プロジェクトでAction Mailboxのジェネレーターを実行したところ、ジェネレーターの主キー設定が反映されず、プロジェクトのマイグレーションを手動で修正する必要があることを知った。Active Storageがプロジェクトの設定済み主キーを使うgemであることは知っているので、Action Mailboxでも同じことをする絶好の機会だと思った。

詳細
このプルリクで追加するAction Mailbox用のmigrations_test.rbは、Active Storageでやっていることを忠実に反映している。
さらに、primary_key_type privateメソッドもAction Mailboxのマイグレーションに追加する。これはプロジェクトの設定済み主キー種別を取り出す。このメソッドもまた、Active Storageのものを忠実にモデリングしている。
同PRより


つっつきボイス:「Active Storageのジェネレータでは設定済み主キーがマイグレーションに反映されるのにAction Mailboxでできてなかったのが修正されたんですね」「Action Mailboxのジェネレータの改修が今になって行われたというのは、Action Mailboxのジェネレータを使っている人がそれだけ少なかったということかな?」

🔗 キャッシュシリアライザのフォーマットに:message_packが追加された

config.active_support.cache_format_version:message_packをオプションで渡せるようになった。:message_packはキャッシュエントリのサイズを削減してパフォーマンスを改善できるが、msgpack gem(>= 1.7.0)が必要。

6.17.0のキャッシュフォーマットで書き込まれたキャッシュエントリは、:message_packキャッシュフォーマットの利用時にも読み込み可能。
さらに、:message_packキャッシュフォーマットで書き込まれたキャッシュエントリは、6.17.0のキャッシュフォーマット利用時にも読み込み可能。
この振る舞いのおかげで、キャッシュ全体を無効にすることなくフォーマット間の移行がやりやすくなる。
Jonathan Hefner
同Changelogより


つっつきボイス:「少し前にActive Supportで例のMessagePackがサポートされるようになっていましたが(ウォッチ20230502)、そのMessagePackがキャッシュシリアライザのデフォルトフォーマットになったんですね: キャッシュのストレージは有限だし、キャッシュサーバーとの通信は軽くなるに越したことはないので、MessagePackで圧縮して効率を上げる方向に進むのはよさそう👍」「従来のキャッシュフォーマットとの互換性も維持されていてありがたい🙏」

msgpack/msgpack-ruby - GitHub

参考: MessagePack: It's like JSON. but fast and small.

🔗 7.1キャッシュフォーマットのbare string値の最適化をサポート

新しい7.1キャッシュフォーマットには、ビューフラグメントなどのbare string値の最適化も含まれている。:message_packキャッシュフォーマットもこの最適化を含めるよう変更された。

新しいアプリではデフォルトで7.1キャッシュフォーマットが使われる。既存のアプリでも、config/application.rbファイルかconfig/environments/*.rbファイルでconfig.load_defaults 7.1またはconfig.active_support.cache_format_version = 7.1を設定すれば、このキャッシュフォーマットを有効にできる。

6.17.0のキャッシュフォーマットで書き込まれたキャッシュエントリは、7.1のキャッシュフォーマットの利用時にも読み込み可能。
Rails 7.1へのアップグレードをローリングデプロイする場合は、アップグレード前のサーバーからキャッシュを読み込む必要があるため、最初のデプロイではキャッシュフォーマットを変更しないようにしておき、その次のデプロイで7.1キャッシュフォーマットを有効にすること。
Jonathan Hefner
同Changelogより


つっつきボイス:「Railsで7.1でMessagePackがデフォルトになったことで、ダンプや読み込みでMessagePackの最適化も使えるようになったんですね: これもよさそう👍」

# 同PRより
Warming up --------------------------------------
            dump 7.0     5.482k i/100ms
            dump 7.1    10.987k i/100ms
Calculating -------------------------------------
            dump 7.0     73.966k (± 6.9%) i/s -    367.294k in   5.005176s
            dump 7.1    127.193k (±17.8%) i/s -    615.272k in   5.081387s

Comparison:
            dump 7.1:   127192.9 i/s
            dump 7.0:    73966.5 i/s - 1.72x  (± 0.00) slower

Warming up --------------------------------------
            load 7.0     7.425k i/100ms
            load 7.1    26.237k i/100ms
Calculating -------------------------------------
            load 7.0     85.574k (± 1.7%) i/s -    430.650k in   5.034065s
            load 7.1    264.877k (± 1.6%) i/s -      1.338M in   5.052976s

Comparison:
            load 7.1:   264876.7 i/s
            load 7.0:    85573.7 i/s - 3.10x  (± 0.00) slower

🔗 rewherenilを渡せるようになった

詳細
この変更によって、Active Recordのrewherenilをパラメータとして渡してもエラーをraiseしないようになる。

変更前

Post.where(id: 1).rewhere(nil).to_sql
#=> ArgumentError (Unsupported argument type:  (NilClass))

変更後

Post.where(id: 1).rewhere(nil)
#=> "SELECT `posts`.* FROM `posts`"

追加情報
現時点では、reorder(nil)で現在のorderを削除できるが、rewhere(nil)だとエラーになる。この変更によってrewhereの実装が変更されてnilをパラメータとして渡せるようになり、reorderと同じになる。

Post.order(:created_at).reorder(nil)
#=> "SELECT `posts`.* FROM `posts`"

同PRより


つっつきボイス:「そういえばrewhereメソッドってありますね」「whereunscopeに相当することをrewhere(nil)でできるようになった、なるほど」「reorder(nil)でorderを削除できるの知りませんでした」「今までunscope(:order)みたいにするものだと思ってたけど、言われてみるとreorder(nil)rewhere(nil)の方がわかりやすいかも」

参考: Rails API rewhere -- ActiveRecord::QueryMethods
参考: Rails API unscope -- ActiveRecord::QueryMethods
参考: Rails API reorder -- ActiveRecord::QueryMethods

🔗 ドキュメント: マイグレーションガイドのSQLite3向けサンプルを修正

再現手順
1. SQLite3を使うRailsアプリを作成する(Rails 7で: これは自分の場合たまたまrails newでデフォルトになっていた)。
2. ガイドの§3.10 Using reversible§3.11 Using the up/down Methods§3.12 Reverting Previous Migrationsを実行する。

期待される振る舞い
ガイドに書かれているマイグレーションが成功する。
実際の結果
SQLite3::SQLException: near "CONSTRAINT": syntax errorでマイグレーションが失敗する。これはSQLite3でALTER TABLE内のADD CONSTRAINTがサポートされていないため(参考: 12
#47941より


つっつきボイス:「マイグレーションガイドのSQLite3のサンプルが実は正しく動かなかったのが修正されたそうです」「今まではSQLite3でサポートされていない書き方だったとは」「このドキュメント修正は7-0-stableにもバックポートしてよさそうなので後でやっておきます」

後でバックポートしてRailsガイドにも反映しました↓。

参考: [ci-skip]Backport 48085 to 7-0-stable branch for updating Migration Guide by hachi8833 · Pull Request #48308 · rails/rails

🔗Rails

🔗 ViewComponent 3.0がリリース


つっつきボイス:「RubyKaigi 2023でEvil Martiansの人たちとランチしているときに、ViewComponent 3.0が4月にリリースされていたことを教わりました」「Rubyでビューのロジックを書けるViewComponentはまだ実践する機会がないけど、何度か述べているように筋はよいものだと思いますし、GitHubが作って熱心にメンテしている点は安心感がありますね」「3.0のChangelog↓を見ると結構breaking changesが多くて、2.xのときから使ってた人はちょっと手間取りそう」

「既にViewComponentを使っているという人によると、やはりHotwireと相性がよいそうです」「どちらもロジックをバックエンドに寄せるものなので相性がいいのは想像がつきますね」

ViewComponent/view_component - GitHub

実践ViewComponent(1): 現代的なRailsフロントエンド構築の心得(翻訳)

🔗 複雑さを指標にするFlog-Driven開発(Ruby Weeklyより)

seattlerb/flog - GitHub


つっつきボイス:「Flogって最初Frog(カエル)のことかと思ったら、鞭でしばくという意味でした」「記事やサイトを見た感じでは、いわゆる"複雑度"(complexity)を指標としてそれを減らすように開発することを指しているようですね」「複雑になるほどつらみが増してスコアが上がるということですか」「複雑度はソフトウェアメトリクスでよく引き合いに出される指標ですね」

最も複雑なコードを、読みやすいペインレポートとして出力します。Flogスコアが高いほどコードのつらみが大きいことを表します。
同記事より: Flogの解説

# 同記事より: メソッドごとのflogスコア
⇒ flog guitar_with_tuning.rb -a
65.6: flog total
9.4: flog/method average

16.8: Guitar#standard_tuning
16.8: Guitar#down_half_step_tuning
13.0: Guitar#tune
6.6: Guitar#pick
5.2: Guitar#initialize
4.3: Guitar#restring
3.0: Guitar#none

参考: 循環的複雑度 - Wikipedia

「それにしてもRubyサディストってすごい名前」「使う側はマゾヒストにならないと😆」「About Usページを見ると、ZenTestとかもやっている人たちなのか: ZenTestはRails 3の頃によく使われていたテスティングフレームワークですね」

seattlerb/zentest - GitHub

🔗 『コードレビューで学ぶRuby on Rails』


つっつきボイス:「技術書典に出展していたこの本↓を電子書籍版でポチりました: Railsアプリケーションのコードレビューで指摘されがちなポイントをまとめた書籍って意外に少ないので助かりました🙏」「こういう情報を集約する人たちがいる開発チームはいいですね👍」

以下はつっつき後に見つけたツイートです。

追記(2023/05/31): 以下の訂正ツイートをお知らせいただいたので貼ります。ありがとうございます!

🔗 Rails 7.1のlink_toRuby Weeklyより)


つっつきボイス:「Rails 7.1のlink_toで使える小技だそうです」「link_toにリンク名とモデルを渡すとそのオブジェクトへのリンクを生成するというのは定番だけど、Rails 7.1からは、モデルにto_sを実装しておくと、link_to@profileのようにモデル名を指定するだけでリンク名を推測してくれる↓ようになるのか: 管理画面のようにあまり凝らない画面を少ない手間で手早く作るときに便利そう👍」「この改修#42234は先週の改修で取り上げてませんでした」

# 同記事より
class Profile < ApplicationRecord
  def to_s
    name
  end
end

link_to @profile
#=> <a href="/profiles/1">Eileen</a>

参考: Let link_to infer link name from Model#to_s by olivierlacan · Pull Request #42234 · rails/rails
参考: §1.12.2 link_to -- Action View ヘルパー - Railsガイド

「記事からリンクされている別記事↓では、条件付きのlink_toを簡潔に書けるlink_to_iflink_to_unlesslink_to_unless_currentも紹介されている」「どれも昔から使えるメソッドですね」

参考: Rails Tricks Issue 1 | Greg Molnar

🔗 IRBの複数行オートコンプリートを止める方法


つっつきボイス:「短い記事なので引用しませんが、IRBの起動オプションで止める方法とIRBのコンフィグで止める方法が紹介されています」「複数行オートコンプリートを止めるのとオートコンプリートそのものを止めるのは方法が別、そうそう」「IRBの複数行オートコンプリートで表示がぶっ壊れたときに止めるのは自分もよくやります」「そういえばRails 7.1でproductionのIRBでオートコンプリートがデフォルトでオフになりましたね(ウォッチ20230125)」「productionで表示が壊れると精神衛生上よくない」

その後、Rails 7.0.5でもproductionでIRBのオートコンプリートがデフォルトでオフになりました(#45383)↓。

Rails 7.0.5がリリースされました


前編は以上です。

バックナンバー(2023年度第2四半期)

週刊Railsウォッチ: Ruby 3.3.0-preview1リリース、in_order_ofのバグ修正ほか(20230525後編)

ソースの表記されていない項目は独自ルート(TwitterやはてブやRSSやruby-jp SlackやRedditなど)です。

Rails公式ニュース

Ruby Weekly

RubyFlow

160928_1638_XvIP4h


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。