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

週刊Railsウォッチ: Rails 7でのimport maps導入、Steepで型を導入、KubernetesでRailsを動かすためのガイドほか(20210830前編)

こんにちは、hachi8833です。以下をお見逃しの方はTwitterの#ginzarailsタグである程度追いかけられると思います。

週刊Railsウォッチについて

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

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

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

今回は以下の公式更新情報からです。本家が2つ先まで進んでいます。

🔗 deprecation warningを一括オプトアウト可能に


つっつきボイス:「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としてトランスパイルせずに出力

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ライブラリは元からオープンなコードなので、難読化のためにわざわざトランスパイルすることもないんですよね」「たしかに」

参考: トランスコンパイラ - Wikipedia

🔗 development環境のNoDatabaseError画面に[Create database]ボタンを追加


つっつきボイス:「お〜、ActiveRecord::NoDatabaseErrorエラー画面にCreate databaseボタンができた」「当然ながらdevelopmentモードにしか出ないようになっている」「UIがますます親切になった👍」


同PRより

🔗 ActiveRecord::QueryMethods#in_order_ofを追加


つっつきボイス:「おぉ、ついにActive Recordにもin_order_ofが入った🎉」「別のものが前からあったんでしょうか?」「少し前にRailsにEnumerable#in_order_ofが入っていたんですが↓、今回それのActive Record版もできて適用範囲が広がってきた感じですね」「なるほど!」

参考: 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で型を導入


つっつきボイス:「これは自分も読みました: RBSを自動生成するところから始めてひととおりやれる、具体的ないい記事👍」「RubyMineのRBS対応も進んでいますし、小さな新規プロジェクトでやってみてもよさそう」

「ちょうどこのツイートも見つけました」「RBSとSteepはRuby 2.6以降から使える、いいですね〜」

🔗 AWS LambdaでRails

aws/aws-lambda-ruby-runtime-interface-client - GitHub


つっつきボイス:「取り上げるのが遅れましたが、7月末の銀座Rails #35の@joker1007さんの発表です」「これもいい発表でした」

「元々Amazon ECSのタスク実行機能が使いにくいという問題があって、この問題は実際に踏んでみないとわかりにくいんですが、その部分をLambdaでやる方がいいという趣旨」

「AWSのコンテナをスケジューリングで動かす方法は現在2とおりあります: 1つはFargateやECSのscheduled taskと呼ばれるもので、コンテナをワンショットでバッチ的に実行する」「ふむふむ」「しかしECSの実行そのものがかなり重いのが不便: 具体的にはECSのイメージが置かれているリポジトリのパスがECSコンテナのタスク定義ファイルに書かれていて、起動のたびにそこからイメージをダウンロードしてECSの実行環境に展開することではじめて実行される」「聞くからに重そうですね...」「下手すると起動に数分かかることもあります」

参考: スケジュールされたタスク - Amazon ECS

「2つ目のLambdaは同じようにコンテナを起動しますが、ECSのタスク起動よりずっと速い」「お〜」「Lambdaにはコンテナサイズや実行時間に制限がありますが、実行時間が短くて何度も実行するようなものならLambdaでやる方がずっといい、というのがスライドのこのあたりの話↓」「なるほど」「ECSは常にECR(Elastic Container Registry)からDockerイメージをダウンロードするのと、タスクスケジューラが毎回コールドスタートするので遅いんですが、Lambdaは起動済みのDockerコンテナがあればウォームスタートできるので数秒おきや数分おきに起動するタスクだと特に速い: ちょうど自分もこのあたりにハマったことがありました」

参考: Amazon ECR(Docker イメージの保存と取得)| AWS

🔗 Rails 7でのimport maps導入

rails/importmap-rails - GitHub


つっつきボイス:「ついこの間話題になった、Rails 7のJSコードをWebpack経由でトランスパイラを通す代わりにimport mapsを使う話の動画について、DHHが記事も書いていたので取り上げました」「これについては既にTwitterにも書きましたけど、今後のRailsがこういうWebpackerレスな流れになることはほぼDHHが決めているようなので、このDHHの記事と解説動画、あとこれに関連する上の#42856の改修内容は一度見て押さえておくことをおすすめします: 技術的にもそれほど難しいものではありませんし、字幕をオンにすれば英語もそれほど大変ではないので」「なるほど」「RailsでTypeScript使いたい人たちはどうなるんだろう」

「ところで、DHHはReactの場合の動画も後追いで公開したんですよ↓」「これは知りませんでした」

「2本目のReact動画は、Railsがトランスパイラを使わなくなるとReactのJSXやTypeScriptなどが書けなくなるという問題を自分も含めていろんな人が指摘したので↓、DHHがJSXについては『こうすれば書けるよ』という回答として公開したものです」

参考: 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ライクな構文で書ける』とあるのでたぶんこれかなと思います」

developit/htm - GitHub

🔗 徳丸先生のRailsセキュリティ関連解説動画


つっつきボイス:「こちらの動画は、銀座Rails #34の徳丸先生のセッションを主催者承認のうえでYouTube動画で公開したそうです」「たしかに銀座Railsで見たヤツ」

「ところで徳丸先生のYouTubeチャンネルにもだいぶ動画が増えていますね」「動画だと見るのに時間がかかるのが大変」「そこですよね」「文章と動画とどちらを好むかは年齢層によって変わってきそうですけど」「せめて動画内でセリフや文字を検索できたらいいかも」「たしかに」「話し言葉と書き言葉はどうしても違ってくるので、自分は記事で読みたいかな」

🔗 KubernetesでRailsを動かす決定版ガイド


つっつきボイス:「KubernetesでRailsを動かす情報を、ドメインまで取って公開しているサイトです」「Kubernetesで単にRailsのDockerイメージを動かしてログを取るぐらいならさほど難しくありませんが、secretの扱いやrakeタスクやマイグレーションのようなRailsで最低限必要なことをひととおり網羅しているようですね: KubernetesでRailsを初めて動かす人向けの入り口として便利そう👍」「お〜」

🔗 その他Rails


つっつきボイス:「@yasaichiさんの発表が以下のスライド↓の続編になりそうなので期待しています」「9/15(水)開催だからRubyKaigi Takeout 2021の翌週か、とりあえず申し込んでおこう」


前編は以上です。

バックナンバー(2021年度第3四半期)

週刊Railsウォッチ: SorbetのRuby AOTコンパイラが公開、「Compiler Explorer」にRubyが追加、Ractorで非同期通信ほか(20210823後編)

今週の主なニュースソース

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

Rails公式ニュース

Ruby Weekly


CONTACT

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