- Ruby / Rails関連
週刊Railsウォッチ: Rails 7でのimport maps導入、Steepで型を導入、KubernetesでRailsを動かすためのガイドほか(20210830前編)
こんにちは、hachi8833です。以下をお見逃しの方はTwitterの#ginzarailsタグである程度追いかけられると思います。
RubyKaigi直前予習企画『タイムテーブル徹底解説』を、今年は銀座Railsさんの場を借りてオンラインで催します。
RubyKaigiマニアの方はもちろん、今回は客層が広そうなので少し敷居を下げて、Rubyの開発に興味がある方なら誰でも何かしらお持ち帰りいただける内容になる予定です。ぜひご参加ください! https://t.co/fvPRDUWLgx— Akira Matsuda (@a_matsuda) August 25, 2021
🔗Rails: 先週の改修(Rails公式ニュースより)
今回は以下の公式更新情報からです。本家が2つ先まで進んでいます。
🔗 deprecation warningを一括オプトアウト可能に
- PR: Allow entirely opting out of deprecation warnings by ghiculescu · Pull Request #42913 · rails/rails
つっつきボイス:「config.active_support.report_deprecations = false
を指定すればdeprecation warningをまとめてオプトアウトできるようになった: 乱用は避けたいけどやむを得ず一時的にそうしたくなることもあるヤツ」「以前は以下を両方指定しないといけなかったんですね」「オプトアウトできる機能はあってもいいと思います👍」
# changelogより
config.active_support.deprecation = :silence
config.active_support.disallowed_deprecation = :silence
🔗 Action CableのJSをES Moduleとしてトランスパイルせずに出力
- PR: Output Action Cable JS without transpiling and as ESM by dhh · Pull Request #42856 · rails/rails
Railsの全JSを可能な限りES2017およびESM(ES Module)をターゲットとするよう更新しよう。これによってバンドルなしでこれらの出力をブラウザで直接利用できるようになり、かつES Moduleを使えるようになる。これはWebpackerなしのデフォルトへの布石となる。
ここでは後方互換性問題の考慮が必要。これが互換性を妨げるのであれば2つの異なる出力を生成してもよい。
同PRより
参考: ブラウザで覚えるES Modules入門 - JavaScriptでモジュールを使う時代 - ICS MEDIA
つっつきボイス:「Rails 7でWebpackerレスを目指す方向」「ESMへトランスパイルせずにJSを出力するようになるといえば、Rails 7のJSがimport mapsベースになる話も出ていますね」「ちょうどこの後でも取り上げています」「考えてみればAction CableのJSライブラリは元からオープンなコードなので、難読化のためにわざわざトランスパイルすることもないんですよね」「たしかに」
🔗 development環境のNoDatabaseError
画面に[Create database]ボタンを追加
つっつきボイス:「お〜、ActiveRecord::NoDatabaseError
エラー画面にCreate databaseボタンができた」「当然ながらdevelopmentモードにしか出ないようになっている」「UIがますます親切になった👍」
🔗 ActiveRecord::QueryMethods#in_order_of
を追加
つっつきボイス:「おぉ、ついにActive Recordにもin_order_of
が入った🎉」「別のものが前からあったんでしょうか?」「少し前にRailsにEnumerable#in_order_of
が入っていたんですが↓、今回それのActive Record版もできて適用範囲が広がってきた感じですね」「なるほど!」
Enumerable#in_order_of. Keep making things a little better every day, and one day you'll wake up in heaven 1.01^365 😄 https://t.co/YcSovsxLFc
— DHH (@dhh) February 4, 2021
参考: rails commit log流し読み(2021/08/05) - なるようになるブログ
概要
これにより、SQL式に基づいてレコードを返す際に明示的な順序を指定できるようになる。デフォルトでは次のようにCASE
で実現される。
Post.in_order_of(:id, [3, 5, 1])
上は以下のSQLを生成する。
SELECT "posts".* FROM "posts" ORDER BY CASE "posts"."id" WHEN 3 THEN 1 WHEN 5 THEN 2 WHEN 1 THEN 3 ELSE 4 END ASC
しかしこの機能はMySQLでは
FIELD
関数の形で組み込まれているので、コネクションアダプタは代わりに次のようなSQLを生成する。
SELECT "posts".* FROM "posts" ORDER BY FIELD("posts"."id", 1, 5, 3) DESC
この機能は#41333でEnumerableに追加された機能に強くインスパイアされている。cc:@dhh
同PRより
「なるほど、in_order_of
のSQLはCASE
文に続いてWHEN 3 THEN 1 WHEN 5 THEN 2...
みたいに展開されるのか: まあそうなるでしょうね」「改行なしだと一瞬考え込んでしまったけど今理解しました」「力技だけどその分わかりやすいかも」「MySQLだとFIELD
関数があるのでこう書けるんですって↓」「in_order_of
はあっていい機能👍」
-- Changelogより
SELECT "posts".* FROM "posts" ORDER BY FIELD("posts"."id", 1, 5, 3) DESC
🔗 ActiveRecord::Relation#structurally_compatible?
が追加
つっつきボイス:「呼び出し元のActiveRecord::Relation
と引数に渡したActiveRecord::Relation
が構造的に互換かどうか、つまり両者が同じカラムをselectしていて互換であればtrueを返すということのようですね」「おぉ?」「たとえば以下の2つ目だとjoins
で両者のカラムが異なっているのでfalse
が返る」
# activerecord/lib/active_record/relation/query_methods.rb#751
# 与えられたリレーションがこのリレーションと構造的に互換性があるかどうかをチェックし、
# エラーを出さずに`#and`や`#or`メソッドを使えるかどうかを判断する。
# 「構造的に互換性がある」は、両者が同じモデルをスコープしていて
# `#where`(`#group`が定義されていない場合)または#having(`#group`が存在する場合)
# によってのみ異なることと定義される。
Post.where("id = 1").structurally_compatible?(Post.where("author_id = 3"))
# => true
Post.joins(:comments).structurally_compatible?(Post.where("id = 1"))
# => false
「そして以下のように両者を#or
でつなげる場合はcurrent.or(other)
で、つなげない場合はModel.where(id: current)
のようにラップしてから#or
でつないでいる」「なるほど」「特にスコープでjoinsされた場合だと#and
や#or
でつないでいいか考えることがちょくちょくあるので、これはあっていいメソッド👍」「名前はちょっと長いけど、知っていたら使うかも」
# 同PRより
relations = [...]
relations.drop(1).inject(relations.first) do |current, other|
if current.structurally_compatible?(other)
current.or(other)
else
Model.where(id: current).or(Model.where(id: other))
end
end
🔗Rails
🔗 RailsプロジェクトにSteepで型を導入
書きました! / 1件のコメント https://t.co/JKfpk59j5P “そろそろRailsプロジェクトに型を導入したい人向けの資料” (1 user) https://t.co/HEvRggs85E
— ksss (@_ksss_) August 26, 2021
つっつきボイス:「これは自分も読みました: RBSを自動生成するところから始めてひととおりやれる、具体的ないい記事👍」「RubyMineのRBS対応も進んでいますし、小さな新規プロジェクトでやってみてもよさそう」
「ちょうどこのツイートも見つけました」「RBSとSteepはRuby 2.6以降から使える、いいですね〜」
Ruby 3じゃないとRBS/Steepが使えないと思っていた、という話をちらほら見る(実際は2.6+で使える)ので、広報がたりないなーとなってる
— 🎹 (@p_ck_) August 26, 2021
🔗 AWS LambdaでRails
つっつきボイス:「取り上げるのが遅れましたが、7月末の銀座Rails #35の@joker1007さんの発表です」「これもいい発表でした」
「元々Amazon ECSのタスク実行機能が使いにくいという問題があって、この問題は実際に踏んでみないとわかりにくいんですが、その部分をLambdaでやる方がいいという趣旨」
「AWSのコンテナをスケジューリングで動かす方法は現在2とおりあります: 1つはFargateやECSのscheduled taskと呼ばれるもので、コンテナをワンショットでバッチ的に実行する」「ふむふむ」「しかしECSの実行そのものがかなり重いのが不便: 具体的にはECSのイメージが置かれているリポジトリのパスがECSコンテナのタスク定義ファイルに書かれていて、起動のたびにそこからイメージをダウンロードしてECSの実行環境に展開することではじめて実行される」「聞くからに重そうですね...」「下手すると起動に数分かかることもあります」
「2つ目のLambdaは同じようにコンテナを起動しますが、ECSのタスク起動よりずっと速い」「お〜」「Lambdaにはコンテナサイズや実行時間に制限がありますが、実行時間が短くて何度も実行するようなものならLambdaでやる方がずっといい、というのがスライドのこのあたりの話↓」「なるほど」「ECSは常にECR(Elastic Container Registry)からDockerイメージをダウンロードするのと、タスクスケジューラが毎回コールドスタートするので遅いんですが、Lambdaは起動済みのDockerコンテナがあればウォームスタートできるので数秒おきや数分おきに起動するタスクだと特に速い: ちょうど自分もこのあたりにハマったことがありました」
参考: Amazon ECR(Docker イメージの保存と取得)| AWS
🔗 Rails 7でのimport maps導入
つっつきボイス:「ついこの間話題になった、Rails 7のJSコードをWebpack経由でトランスパイラを通す代わりにimport mapsを使う話の動画について、DHHが記事も書いていたので取り上げました」「これについては既にTwitterにも書きましたけど、今後のRailsがこういうWebpackerレスな流れになることはほぼDHHが決めているようなので、このDHHの記事と解説動画、あとこれに関連する上の#42856の改修内容は一度見て押さえておくことをおすすめします: 技術的にもそれほど難しいものではありませんし、字幕をオンにすれば英語もそれほど大変ではないので」「なるほど」「RailsでTypeScript使いたい人たちはどうなるんだろう」
Youtubeのdhh channelにRails 7でWebpack(及びJSの事前ビルド)を使わずにモダンフロントエンドするぜというAlphaデモが出ていた。クライアントはscript importmapを使ってJSライブラリの読み込みをすればええやろ、という提案(続 https://t.co/KPRNJDaeCh
— Masato Mori (@morimorihoge) August 16, 2021
Rails側でimport-mapするライブラリを管理することで、MPAでありがちな「このページだけはこのライブラリを読み込みたい」みたいなケースをサーバーサイド側で出しわけすることができる。確かに現状のWebpack使った実装に比べるとシンプルで動きが追いやすいようには見えた(続
— Masato Mori (@morimorihoge) August 16, 2021
「ところで、DHHはReactの場合の動画も後追いで公開したんですよ↓」「これは知りませんでした」
「2本目のReact動画は、Railsがトランスパイラを使わなくなるとReactのJSXやTypeScriptなどが書けなくなるという問題を自分も含めていろんな人が指摘したので↓、DHHがJSXについては『こうすれば書けるよ』という回答として公開したものです」
そういう意味ではRailsエンジニア(JSもチョトデキル)がプロトタイピング的に小さなものを作ってリリースするのには悪くなさそうだけども、大きいものを作るのにはどうかなあ、という印象だった。管理画面くらいならありかも
— Masato Mori (@morimorihoge) August 16, 2021
参考: JSX の導入 – React
「ところが2本目の動画を見ると実際にはJSXそのものを書けるのではなくて、どうやらJSファイルにJSXライクなコードを書けるh
というヘルパーを使うみたいなんですよ: import html from "htm"
というコードをたどるとdevelopit/htmというライブラリがどうもそれみたい」「ありゃ」
Alpha preview: Using React with importmaps on Rails 7 - YouTubeより
「developit/htmのREADMEにも『プレーンなJavaScriptにトランスパイラなしでJSXライクな構文で書ける』とあるのでたぶんこれかなと思います」
🔗 徳丸先生のRailsセキュリティ関連解説動画
つっつきボイス:「こちらの動画は、銀座Rails #34の徳丸先生のセッションを主催者承認のうえでYouTube動画で公開したそうです」「たしかに銀座Railsで見たヤツ」
「ところで徳丸先生のYouTubeチャンネルにもだいぶ動画が増えていますね」「動画だと見るのに時間がかかるのが大変」「そこですよね」「文章と動画とどちらを好むかは年齢層によって変わってきそうですけど」「せめて動画内でセリフや文字を検索できたらいいかも」「たしかに」「話し言葉と書き言葉はどうしても違ってくるので、自分は記事で読みたいかな」
🔗 KubernetesでRailsを動かす決定版ガイド
つっつきボイス:「KubernetesでRailsを動かす情報を、ドメインまで取って公開しているサイトです」「Kubernetesで単にRailsのDockerイメージを動かしてログを取るぐらいならさほど難しくありませんが、secretの扱いやrakeタスクやマイグレーションのようなRailsで最低限必要なことをひととおり網羅しているようですね: KubernetesでRailsを初めて動かす人向けの入り口として便利そう👍」「お〜」
Found this guide written by @collimarco about deploying Rails in Kubernetes and it's so great. A fast static site with clear instructions, no "sign up for my newsletter", scroll-jacking, weird formatting. Just plain, simple and well structured. Thanks!https://t.co/uvLS5Ci9BR
— Philipp Defner (@tehwey) January 22, 2020
🔗 その他Rails
つっつきボイス:「@yasaichiさんの発表が以下のスライド↓の続編になりそうなので期待しています」「9/15(水)開催だからRubyKaigi Takeout 2021の翌週か、とりあえず申し込んでおこう」
前編は以上です。
バックナンバー(2021年度第3四半期)
週刊Railsウォッチ: SorbetのRuby AOTコンパイラが公開、「Compiler Explorer」にRubyが追加、Ractorで非同期通信ほか(20210823後編)
- 20210818前編 カウンタキャッシュをスレッドセーフに更新、Journey::Ast追加、GitLabをAWS Graviton2で動かすほか
- 20210810 システムテスト用headlessドライバにCupriteが追加、rails-mini-profiler、Jeremy Evansインタビューほか
- 20210804後編 Rubyの可変長アロケーションプロジェクト、サーキットブレーカーgem、EC2-Classicが終了へほか
- 20210803前編 SorbetでRailsアプリの型シグネチャを書く、activerecord-cte gemとanycable-client gem
- 20210720後編 ruby-gitでGit操作、最近のruby/debug、stdgems.org、Windows 365 Cloud PCほか
- 20210719前編 GitHubによるdisable_joins解説、MemoWise gemでメモ化、RailsのDDoS攻撃対策ほか
- 20210713後編 ruby-spacyで自然言語処理、Ruby製x86-64アセンブラ、『タイムゾーン呪いの書』ほか
- 20210712前編 AR::Relation#destroy_allがバッチ分割に変更、Active Record暗号化解説、sidekiq-unique-jobsほか
- 20210706後編 GitHub CopilotのAI補完、Pure Ruby実装のRuby JIT rhizome、PostgreSQLのPG-Strom拡張ほか
- 20210705前編 DI的な書き方が必要なとき、脆弱性学習用アプリRailsGoat、brakemanは優秀ほか
今週の主なニュースソース
ソースの表記されていない項目は独自ルート(TwitterやはてブやRSSやruby-jp SlackやRedditなど)です。
週刊Railsウォッチについて
TechRachoではRubyやRailsなどの最新情報記事を平日に公開しています。TechRacho記事をいち早くお読みになりたい方はTwitterにて@techrachoのフォローをお願いします。また、タグやカテゴリごとにRSSフィードを購読することもできます(例:週刊Railsウォッチタグ)