- Ruby / Rails関連
週刊Railsウォッチ: RailsチュートリアルがRails 7対応版をリリース、ViewComponentで使えるLookbookほか(20221115前編)
こんにちは、hachi8833です。Ruby 3.2.0 Preview 3がリリースされました。ReDoS対策も追加されています。
Link: Ruby 3.2.0 Preview 3 リリース
https://t.co/LmaA67lbCE— Yukihiro Matz (@yukihiro_matz) November 12, 2022
🔗Rails: 先週の改修(Rails公式ニュースより)
- 公式更新情報: Ruby on Rails — More intuitive checking of form check boxes and radio buttons
- 公式更新情報: Ruby on Rails — An improved error page, groundwork for composite primary keys and Stimulus 3.1.1
🔗 check_box_tag
とradio_button_tag
でchecked:
キーワード引数が利用可能になった
このAPIを
FormHelper
の類似メソッドにより近づける。以下のように、checked
を位置引数(通常の引数)でもキーワード引数でも指定できる。= check_box_tag "admin", "1", false = check_box_tag "admin", "1", checked: false = radio_button_tag 'favorite_color', 'maroon', false = radio_button_tag 'favorite_color', 'maroon', checked: false
Alex Ghiculescu
同Changelogより
参考: Rails API check_box_tag
-- ActionView::Helpers::FormTagHelper
参考: Rails API radio_button_tag
-- ActionView::Helpers::FormTagHelper
つっつきボイス:「この改修はありがたい👍」「位置引数でfalse
を単体で渡すよりキーワード引数でchecked: false
と書ける方が全然わかりやすいですよね」「つい最近もこのパラメータを渡し間違えました」
🔗 DBアダプタの#execute
メソッドにallow_retry
オプションを渡せるようになった
アダプタの
#execute
メソッドにallow_retry
オプションを指定可能になった。true
に設定すると、コネクション関連のエラーが発生したときに、データベース設定のconnection_retries
値に達するまでSQLステートメントがリトライされる。
Adrianna Chang
同Changelogより
動機と背景
リトライの振る舞いをオプトインするには#execute
メソッド全体の再実装が必要。もしその代わりに#execute
にallow_retry
オプションを受け取れる形にすれば、アプリが#execute
にパッチを当ててsuperをallow_retry: true
で呼び出せるようになる。
追加情報
リトライをすべてのクエリで有効にするコンフィグを追加することを検討したが、ShopifyやGitHubのアプリケーションではさほど深く考えずにすべてのクエリをリトライするようになったという歴史はあるものの、これはRailsに導入する設定としてはリスクが大きすぎると判断した。#execute
を変更するのは妥協点としてはよさそうに思える。アプリがリトライの振る舞いを得るには引き続き#execute
に意図的にパッチを当てなければならないが、しかしこの方法なら私たちのパッチがメソッド全体を再実装せずに済むので、パッチがもろくなりにくい。
同PRより
つっつきボイス:「SQLのリトライをallow_retry
オプションで指定できるようになったのはうまい方法かも」「デフォルトではオフなんですね」「Multi-AZ failoverで接続先のRDSインスタンスが切り替わるときなどは最初に一度失敗してから再接続することになるけど、そういうときのコネクション再接続も含めてリトライできるなら純粋に嬉しい👍」「この機能が必要な理由がわかりますね」
参考: Amazon RDS(マネージドリレーショナルデータベース)| AWS
🔗 リクエストのparameter_filter
がpublicメソッドになった
これは、リクエストと同じパラメータフィルタに基づいて独自のハッシュをフィルタしたい場合に便利。
例: 例外の通知やログ出力でヘッダーやカスタム値をリクエストから読み込む必要があり、なおかつそれらをフィルタしたい場合。
同PRより
つっつきボイス:「Railsのログで値を出力しないときに使うconfig.filter_parameters
メソッドを公式APIとして使えるようにしたんですね」「ログでFILTERED
にするときのヤツですね」「例外通知やログをカスタム処理するときにこのメソッドで処理したりできる、なるほど」
# actionpack/test/dispatch/request_test.rb#1289
test "parameter_filter returns the same instance of ActiveSupport::ParameterFilter" do
request = stub_request(
"action_dispatch.parameter_filter" => [:secret]
)
filter = request.parameter_filter
assert_kind_of ActiveSupport::ParameterFilter, filter
assert_equal({ "secret" => "[FILTERED]", "something" => "bar" }, filter.filter("secret" => "foo", "something" => "bar"))
assert_same filter, request.parameter_filter
end
参考: § 3.1.21 config.filter_parameters
-- Rails アプリケーションを設定する - Railsガイド
🔗 schema.rbの外部キーやCHECK制約にvalidate: false
を追加するようになった(PostgreSQL)
従来は、外部キーやCHECK制約を追加するときに
validate: false
を指定してもschema.rbに記録していなかった。そのため、このスキーマからデータベースを復元すると外部キーやCHECK制約の検証ができなくなる可能性があった。
Tommy Graves
同Changelogより
動機/背景
現在は、validate: false
は外部キーやCHECK制約(validate機能をサポートするデータベースの場合)についてschema.rbでトラッキングできない。つまり、このスキーマをリストアすると、すべての外部キーやCHECK制約が(それまで一度も検証されたことがなくても)常に検証されることになる。
詳細
このプルリクは、外部キーやCHECK制約が正しくない場合にschema.rbのadd_foreign_key
とadd_foreign_key
にvalidate: false
を追加する。これらが正しい場合はvalidate: true
にしない(これがデフォルトなので)。
同PRより
つっつきボイス:「このプルリク自体は、従来マイグレーションで外部キーやCHECK制約にvalidate: false
を指定してもschema.rbに反映されていなかったのを反映するようにしたということですね」「APIドキュメントを見ると、add_foreign_key
やadd_check_constraint
のvalidate:
オプションはPostgreSQLのみの機能だそうです↓」「ホントだ」
参考: Rails API add_foreign_key
-- ActiveRecord::ConnectionAdapters::SchemaStatements
参考: Rails API add_check_constraint
-- ActiveRecord::ConnectionAdapters::SchemaStatements
「ところでこのvalidate
オプションって何だろう?」「制約そのものと別に検証のオプションがあるってよくわからない」「マイグレーションで使う機能なのはたしかだけど」(しばし調べる)「どうやらこのVALIDATE CONSTRAINTのようですね↓」
参考: PostgreSQL 14ドキュメント ALTER DOMAIN
VALIDATE CONSTRAINT
この構文は、以前にNOT VALID
として追加された制約を検証します。 つまり、そのドメイン型のテーブル列の値すべてが指定された制約を満たすかどうかを検証します。
www.postgresql.jpより
「ALTERを使って後付けで制約を加えるときに、今入っている既存のデータに対してバリデーションするかどうかを指定するのがVALIDATE CONSTRAINTということみたい」「あ〜、なるほど」「制約は加えたいけど既存の古いデータは事情があって変えたくないのでバリデーションしたくないことってありそうですね」「これは知らなかった」「デフォルトはtrueなんですね」「ぽすぐれは新しい機能の発見がいつもありますね」
🔗 ActiveRecord::Base
オブジェクトのクエリでカラムのリストを指定可能になった
ActiveRecord::Base
オブジェクトの更新、削除、再読み込み時のSQLクエリビルドに利用できるカラムリストを指定可能になった。class Developer < ActiveRecord::Base query_constraints :company_id, :id end developer = Developer.first.update(name: "Bob") # => UPDATE "developers" SET "name" = 'Bob' WHERE "developers"."company_id" = 1 AND "developers"."id" = 1
Nikita Vasilevsky
同Changelogより
つっつきボイス:「"composite primary keys"とあるので、複合主キーに関連している機能追加らしい」「プルリクにも、今後Railsで複合主キーをサポートするための準備の一環とも書かれていますね」「お〜期待しちゃいます」「query_constraints
はもっといい名前にできそうな気はするけど今後に期待したい」
参考: 複合主キーとは - 意味をわかりやすく - IT用語辞典 e-Words
🔗 夏時間が終わるときのTime#change
と#advance
を修正
従来は、
Time#change
やTime#advance
が夏時間(DST: Daylight Saving Time)の最後のストレッチの中で時刻を構築すると、ローカル時刻では常にDSTでないオフセットが選択されていた。# DSTはUS/Easternで2021-11-07 2:00:00 AMの直前に終了する ENV["TZ"] = "US/Eastern" time = Time.local(2021, 11, 07, 00, 59, 59) + 1 # => 2021-11-07 01:00:00 -0400 time.change(day: 07) # => 2021-11-07 01:00:00 -0500 time.advance(seconds: 0) # => 2021-11-07 01:00:00 -0500 time = Time.local(2021, 11, 06, 01, 00, 00) # => 2021-11-06 01:00:00 -0400 time.change(day: 07) # => 2021-11-07 01:00:00 -0500 time.advance(days: 1) # => 2021-11-07 01:00:00 -0500
そして
TimeZone
オブジェクトの時刻に対しては常にDSTオフセットが選択されてしまうことになる。Time.zone = "US/Eastern" time = Time.new(2021, 11, 07, 02, 00, 00, Time.zone) - 3600 # => 2021-11-07 01:00:00 -0500 time.change(day: 07) # => 2021-11-07 01:00:00 -0400 time.advance(seconds: 0) # => 2021-11-07 01:00:00 -0400 time = Time.new(2021, 11, 8, 01, 00, 00, Time.zone) # => 2021-11-08 01:00:00 -0500 time.change(day: 07) # => 2021-11-07 01:00:00 -0400 time.advance(days: -1) # => 2021-11-07 01:00:00 -0400
修正後は、
Time#change
とTime#advance
は可能な場合に元の時刻のオフセットと一致するオフセットを選択するようになる。ENV["TZ"] = "US/Eastern" time = Time.local(2021, 11, 07, 00, 59, 59) + 1 # => 2021-11-07 01:00:00 -0400 time.change(day: 07) # => 2021-11-07 01:00:00 -0400 time.advance(seconds: 0) # => 2021-11-07 01:00:00 -0400 time = Time.local(2021, 11, 06, 01, 00, 00) # => 2021-11-06 01:00:00 -0400 time.change(day: 07) # => 2021-11-07 01:00:00 -0400 time.advance(days: 1) # => 2021-11-07 01:00:00 -0400 Time.zone = "US/Eastern" time = Time.new(2021, 11, 07, 02, 00, 00, Time.zone) - 3600 # => 2021-11-07 01:00:00 -0500 time.change(day: 07) # => 2021-11-07 01:00:00 -0500 time.advance(seconds: 0) # => 2021-11-07 01:00:00 -0500 time = Time.new(2021, 11, 8, 01, 00, 00, Time.zone) # => 2021-11-08 01:00:00 -0500 time.change(day: 07) # => 2021-11-07 01:00:00 -0500 time.advance(days: -1) # => 2021-11-07 01:00:00 -0500
Kevin Hall, Takayoshi Nishida, and Jonathan Hefner
同Changelogより
つっつきボイス:「こちらはバグ修正です」「夏時間の境界条件で起きるバグはつらそう...」「そういえば米国で夏時間やめようみたいな話が持ち上がってましたよね↓」
参考: 「夏時間を恒久化する法案」が全会一致でアメリカ連邦議会上院を通過 - GIGAZINE
🔗Rails
🔗 RailsチュートリアルがRails 7対応版をリリース
#Railsチュートリアル からRails 7対応のWebテキスト(第7版)を先行リリースしました! 🎓🆕#Hotwire や #Importmap など多くの変更点が加わった第7版の魅力をnote記事にまとめたので、ぜひご一読いただけると嬉しいです...!! 🙏💖
🎓 Rails 7 対応Webテキスト先行リリース https://t.co/oxRgLkKxCH pic.twitter.com/9h4pp0yN4C
— Railsチュートリアル 🎓 (@RailsTutorialJP) November 8, 2022
つっつきボイス:「7対応版ついに出た🎉」「先行リリースのWeb版に加えて電子書籍版(EPUB/PDF)もリリースされたので、今後は解説動画もリリースされるそうです」「こういう教科書を日本語で読めるのは貴重」「訳文の改定・改善もすごく進んでいます」「実際に教育や研修の現場で使いながら継続的に修正を加えていく手法は、多くの人に使われるほど改善がはかどるのが強いですよね」
参考: Ruby on Rails チュートリアル:プロダクト開発の0→1を学ぼう
参考: 電子書籍でプロダクト開発を学ぼう - Railsチュートリアル
「こちらは11/11(金)のRubyWorld Conferenceでも発表される予定です↓(注: イベントは終了しました)」「Railsチュートリアルを使った授業の受講者評点が学内最高スコア、すごい」
東京都の公立大学院『AIIT (@AIIT4u)』の受講者評点で、4.73 / 5.00 点の最高スコアを取りました!!(第1クオータの全教科で最高点! 💯🏆)
11月に開催される #RubyWorld Conference で詳細を発表させていただくことになったので頑張ります!! 💪💖 #Raisチュートリアル
📜 https://t.co/tQygyOk7HE https://t.co/x3MbvwDpup pic.twitter.com/g2Or5JaRbI
— 安川要平/Yohei Yasukawa (@yasulab) October 6, 2022
以下はRubyWorld Conference 2022 Day2の当該動画です(4:49:29)。
参考: YouTubeチャンネル RubyWorld Conference
🔗 Railsアプリをスケールさせる方法
つっつきボイス:「AppSignalの記事です」「キャッシュを始めとする定番の手法をまとめた感じですね」「スケールするときは記事のような順序で検討する感じでしょうか?」「キャッシュして効果が出るかどうかなどはリクエストによっても違ってくるので一概には言えないでしょうね」「なるほど」
🔗 Primer ViewComponents
つっつきボイス:「GitHubが作ったものだそうです」「以下の"Primer Design System"の一環としてViewComponent用のコンポーネント集をGitHubが作ったんですね」
「おそらくGitHub自身もRailsのViewComponentでこれを使っているんでしょうね: Design Systemはコンポーネントと相性がいいので実際に使っていそう」「GitHubなら自動生成してるかもしれませんね」「Design Systemとして整備されていてよさそう👍」
「ところでこのOcticonはGitHub独自の用語でしょうね↓」「GitHubが定義したアイコン集をこう呼んでいるんですね」
参考: Octicon | Primer ViewComponents
🔗 Lookbook: ViewComponent向けのストーリーブック
つっつきボイス:「Evil MartiansのViewComponent記事で、Reactとかでよく使われているStorybook.js↓のRuby版として、GitHubが作ったこのLookbookが紹介されていました」「Railsエンジンの形になっていて、これでストーリーブックを見られるようになっているんですね: たしかにViewComponentを使うならストーリーブック的なものが欲しくなるし、ないと困る」
参考: Storybook: Frontend workshop for UI development
参考: ViewComponent in the Wild II: supercharging your components—Martian Chronicles, Evil Martians’ team blog
🔗 ストーリーブック
「ストーリーブックはここ10年ぐらいで登場した概念で、コンポーネントをそこで直接動かしてプレビューできるのが重要」「ふむふむ」「各コンポーネントがどんな外観でどんなふうに動作するかを、アプリ全体を動かさなくてもその場で確かめられるし、コード変更も即座に反映されるので、コンポーネント単位のデザイン修正などがとてもやりやすくなります」「なるほど!」
「たとえば会員登録や決済などのフローで、最後の画面デザインだけ修正しようとすると、表示するためにデータを用意するなどの準備や多くの操作が必要になりますけど、ストーリーブックならデータすら不要で即座に確認・修正できる」「これは欲しくなるヤツ」「ストーリーブックは一度体験するととてもいいものだとわかるので、Lookbookも期待できそう👍」「GitHubはLookbookをもっと宣伝してもいいと思います」
🔗 HerokuのEco DynoとPostgres Miniプラン
今朝公開したブログです。Herokuの無料プランを使っている場合は11月28日までに対応しましょう!
HerokuのEco DynoとPostgres Miniプラン(低額プラン)に移行してみた - give IT a try https://t.co/6j8DrKiAUT
— Junichi Ito (伊藤淳一) (@jnchito) November 8, 2022
つっつきボイス:「jnchitoさんの記事です」「Eco DynoとPostgres Miniが低額で提供されるようになったんですね」「月5ドルならまあまあかな」「PostgreSQL Miniの"最大1万行"はかなりつらそう」「普通に使ってたら1万行なんてすぐですよね」「かといって外部DBに置くと遅くなるだろうし統合性も落ちるんですよね」
🔗 Sidekiq 7.0(Ruby Weeklyより)
つっつきボイス:「Sidekiq 7.0ではグラフ表示が改善されてきれいになったんですって↓」「ほほ〜前よりリッチになってますね」「見た目は大事」「JSONにシリアライズできないオブジェクトをジョブ登録時に引数として渡すとジョブの実行に失敗するので、perform_async
にそういうものを渡すとエラーになるようになったとも書かれていますね」
前編は以上です。
バックナンバー(2022年度第4四半期)
週刊Railsウォッチ: 書籍『Programming Ruby 3.2 (5th Edition)』、ReDoSチェックサイトほか(20221102後編)
- 20221101前編 Packwerkの詳しい解説書『Gradual Modularization for Ruby and Rails』ほか
- 20221026後編 Ruby 3.2のData.define、RubyPrize 2022最終ノミネート、Puma-dev gemほか
- 20221025前編 rodauth-rails gem作者の解説記事、turbo-railsの有料チュートリアルほか
- 20221019後編 Ruby技術者認定試験再受験無料キャンペーン、Starlink日本で販売開始ほか
- 20221018前編 Rails向けLanguage Server “refreshing”開発中、JetBrains Fleetほか
- 20221012後編 RailsとPostgreSQLで列挙型を作成する6つの方法、Ubuntu Proほか
- 20221011前編 Turbo 7.2.0リリース、GitLabのDevSecOpsサーベイ結果ほか
- 20221004後編 ヒアドキュメント拡張の提案、『組織に自動テストを根付かせる戦略』ほか
- 20221003前編 Kaigi on Rails 2022のタイムテーブル発表、書籍『Practicing Rails』ほか
ソースの表記されていない項目は独自ルート(TwitterやはてブやRSSやruby-jp SlackやRedditなど)です。
週刊Railsウォッチについて
TechRachoではRubyやRailsなどの最新情報記事を平日に公開しています。TechRacho記事をいち早くお読みになりたい方はTwitterにて@techrachoのフォローをお願いします。また、タグやカテゴリごとにRSSフィードを購読することもできます(例:週刊Railsウォッチタグ)