- Ruby / Rails関連
週刊Railsウォッチ: キャッシュシリアライザに`:message_pack`が追加、ViewComponent 3リリースほか(20230530前編)
こんにちは、hachi8833です。
🔗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.1
や7.0
のキャッシュフォーマットで書き込まれたキャッシュエントリは、:message_pack
キャッシュフォーマットの利用時にも読み込み可能。
さらに、:message_pack
キャッシュフォーマットで書き込まれたキャッシュエントリは、6.1
や7.0
のキャッシュフォーマット利用時にも読み込み可能。
この振る舞いのおかげで、キャッシュ全体を無効にすることなくフォーマット間の移行がやりやすくなる。
Jonathan Hefner
同Changelogより
つっつきボイス:「少し前にActive Supportで例のMessagePackがサポートされるようになっていましたが(ウォッチ20230502)、そのMessagePackがキャッシュシリアライザのデフォルトフォーマットになったんですね: キャッシュのストレージは有限だし、キャッシュサーバーとの通信は軽くなるに越したことはないので、MessagePackで圧縮して効率を上げる方向に進むのはよさそう👍」「従来のキャッシュフォーマットとの互換性も維持されていてありがたい🙏」
参考: 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.1
や7.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
🔗 rewhere
にnil
を渡せるようになった
詳細
この変更によって、Active Recordのrewhere
にnil
をパラメータとして渡してもエラーを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
メソッドってありますね」「where
のunscope
に相当することを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
がサポートされていないため(参考: 1、2)
#47941より
つっつきボイス:「マイグレーションガイドのSQLite3のサンプルが実は正しく動かなかったのが修正されたそうです」「今まではSQLite3でサポートされていない書き方だったとは」「このドキュメント修正は7-0-stableにもバックポートしてよさそうなので後でやっておきます」
後でバックポートして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と相性がよいそうです」「どちらもロジックをバックエンドに寄せるものなので相性がいいのは想像がつきますね」
🔗 複雑さを指標にするFlog-Driven開発(Ruby Weeklyより)
- 元記事: Flog-Driven Development - Kevin Murphy
- サイト: Confessions of a Ruby Sadist The time has come to show your code who’s boss.
つっつきボイス:「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
「それにしてもRubyサディストってすごい名前」「使う側はマゾヒストにならないと😆」「About Usページを見ると、ZenTestとかもやっている人たちなのか: ZenTestはRails 3の頃によく使われていたテスティングフレームワークですね」
🔗 『コードレビューで学ぶRuby on Rails』
弊社ソニックガーデンからもRails関連の本が出ます!(って書いたら追加してもらえますか?👀 )
「 技術書典14 」にて3種の技術書を頒布します - SonicGarden 株式会社ソニックガーデン https://t.co/5jbJ7Z5obY https://t.co/UzK21tuiag
— Junichi Ito (伊藤淳一) (@jnchito) May 18, 2023
つっつきボイス:「技術書典に出展していたこの本↓を電子書籍版でポチりました: Railsアプリケーションのコードレビューで指摘されがちなポイントをまとめた書籍って意外に少ないので助かりました🙏」「こういう情報を集約する人たちがいる開発チームはいいですね👍」
以下はつっつき後に見つけたツイートです。
電子版ならいつでも買えるんでしょ?って思ってたら6月4日(日)までだった。1冊1000円だし、迷ってるならポチった方がいいかも? #技術書典 #技術書典14
> 電子本の購入は、2023年5月20日(土)〜2023年6月4日(日)の期間に可能ですhttps://t.co/5jbJ7Z5W1w
— Junichi Ito (伊藤淳一) (@jnchito) May 30, 2023
追記(2023/05/31): 以下の訂正ツイートをお知らせいただいたので貼ります。ありがとうございます!
【お詫びと訂正】すいません、上記のツイートに間違いがありました。
❌電子本の購入は2023年6月4日まで
✅電子本は今後も引き続き購入可能「オンライン開催の終了日=電子本の販売終了日」と勘違いしてしまいました。大変申し訳ありません🙇🏻♂️ #技術書典 #技術書典14https://t.co/aCAcqNdrbQ
— Junichi Ito (伊藤淳一) (@jnchito) May 30, 2023
🔗 Rails 7.1のlink_to
(Ruby 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_if
やlink_to_unless
、link_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)↓。
前編は以上です。
バックナンバー(2023年度第2四半期)
週刊Railsウォッチ: Ruby 3.3.0-preview1リリース、in_order_ofのバグ修正ほか(20230525後編)
- 20230524前編 withで作成したリレーションをjoinsで指定可能に、キャッシュストアの例外処理を統一ほか
- 20230502 スライド『Rails 7.1をn倍速くした話』、Rails 7.1でMessagePackをサポートほか
- 20230427後編 第1回Rails Worldが10月に開催、『研鑽Rubyプログラミング』でRuby本体も高速化ほか
- 20230425前編 Rails 7.1の複合主キー対応が引き続き進む、exceptメソッドにwithoutエイリアスが追加ほか
- 20230413後編 ShopifyのRubyパーサーyarp、RJITを書いた理由ほか
- 20230412前編 複合主キーの実装が進む、Rails公式のバグ再現用テンプレートほか
- 20230406後編 Rubyオブジェクトモデルクイズの最難問ほか
- 20230405前編 Arel::Nodes::NodeにAPIドキュメントが追加、rubocop-mdほか
ソースの表記されていない項目は独自ルート(TwitterやはてブやRSSやruby-jp SlackやRedditなど)です。
週刊Railsウォッチについて
TechRachoではRubyやRailsなどの最新情報記事を平日に公開しています。TechRacho記事をいち早くお読みになりたい方はTwitterにて@techrachoのフォローをお願いします。また、タグやカテゴリごとにRSSフィードを購読することもできます(例:週刊Railsウォッチタグ)