- Ruby / Rails関連
週刊Railsウォッチ: Ruby 3.2.0 Preview 1リリース、Rails向けDocker環境ジェネレータ、scientist gemほか(20220404前編)
こんにちは、hachi8833です。昨日付けで早くもRuby 3.2.0 Preview 1がリリースされました。WASIベースのWebAssemblyサポートが目玉です。個人的には正規表現のタイムアウト機能が楽しみです。
Ruby 3.2.0 Preview 1 Released https://t.co/a2FQPVBDph
— Ruby Programming Language (@rubylangorg) April 3, 2022
🔗Rails: 先週の改修(Rails公式ニュースより)
以下のChangelogを中心に見繕いました。コミットの大半がスペル修正でした。
- 公式更新情報: Ruby on Rails — Security improvements, reducing bytes and more!
- 更新差分: Comparing @{2022-03-25}...main@{2022-03-31} · rails/rails
🔗 importmapを使わない場合にbin/setupでyarnをインストールする
はい皆さん👋
このプルリクが有効かどうかはわからないけど(IDK: I don't know)、何か気づいたら教えて欲しい。
af7428c以降bin/setupからyarnインストールがなくなっている。自分はRails 7でプロジェクトを作成してesbuildを使っているが、依存関係を更新したかったのでbin/setupに自分でyarnを追加した。
このコミットは、importmapを使わない場合にsetupスクリプトにyarnのインストールを追加する。
同PRより
つっつきボイス:「コードを見るとesbuildやwebpackやrolloutが有効な場合はyarnをインストールするようになった↓」「このセットアップならyarnは必要ですよね」
# railties/lib/rails/generators/rails/app/templates/bin/setup.tt#L18
+<% if ["webpack", "esbuild", "rollup"].include?(options.javascript) -%>
+
+ # Install JavaScript dependencies
+ system("yarn check --check-files") || system!("yarn install")
+<% end -%>
+
🔗 sanitize_sql_like
のパフォーマンス改善
# activerecord/lib/active_record/sanitization.rb#L109
def sanitize_sql_like(string, escape_character = "\\")
- pattern = Regexp.union(escape_character, "%", "_")
- string.gsub(pattern) { |x| [escape_character, x].join }
+ if string.include?(escape_character) && escape_character != "%" && escape_character != "_"
+ string = string.gsub(escape_character, '\0\0')
+ end
+
+ string.gsub(/(?=[%_])/, escape_character)
end
つっつきボイス:「エスケープ文字そのもののエスケープ処理と%
や_
の処理を分けた感じ」「いきなり正規表現の置き換えをせずにinclude?
で確認してから行う」「正規表現じゃない方が速い、なるほど」「かなり速くなってますね」「sanitize_sql_like
はお世話になることが多いのでありがたい👍」
- Rails API:
sanitize_sql_like
--ActiveRecord::Sanitization::ClassMethods
- Ruby API:
Array#include?
(Ruby 3.1 リファレンスマニュアル)
🔗 db:mysql:build
でユーザー作成とGRANTを自動化
つっつきボイス:「お、これは地味にありがたそう」「今まで手動でやっていたけどそろそろ自動化しようという感じかしら」「.devcontainerにあったということは↓、今までテストには入っていたのをdb:mysql:build
というRakeタスクでできるようにしたんでしょうね」
# .devcontainer/boot.sh#L16
# Create MySQL database and databases
-MYSQL_PWD=root sudo mysql -uroot <<SQL
-CREATE USER 'rails'@'localhost';
-CREATE DATABASE activerecord_unittest DEFAULT CHARACTER SET utf8mb4;
-CREATE DATABASE activerecord_unittest2 DEFAULT CHARACTER SET utf8mb4;
-GRANT ALL PRIVILEGES ON activerecord_unittest.* to 'rails'@'localhost';
-GRANT ALL PRIVILEGES ON activerecord_unittest2.* to 'rails'@'localhost';
-GRANT ALL PRIVILEGES ON inexistent_activerecord_unittest.* to 'rails'@'localhost';
-SQL
+cd activerecord
+MYSQL_CODESPACES=1 bundle exec rake db:mysql:build
「昨今はDocker環境が普通なのでローカル開発ではわざわざユーザーを作らなくてもrootでいいとやいう気持ちはありますね: 本番環境はいずれにしろセッティングは変えますし」「たしかに」
「Dockerでデータベースのコンテナを気軽に生成できるようになったおかげで、昔のようにローカルPCで複数のデータベースアカウントをわざわざ作ったりポート番号をずらしたりすることもめっきりなくなりましたね」「ローカルでMySQLの5.6と5.7を共存させたりしてたな〜」「10年前にあったらとても嬉しかった機能かも」
🔗 NoMethodError
でRails::Railtie
オブジェクト全体を出力しないよう修正
# railties/lib/rails/railtie.rb#L250
+ def inspect # :nodoc:
+ "#<#{self.class.name}>"
+ end
つっつきボイス:「なるほど、Rails::Railtie
の.class.name
だけを出力するようにした↓」「全部をドバっと出されるよりいいですよね」
class A
def initialize(session)
@A = session
end
end
test = A.new("*" * 36)
test.dsad # undefined method `dsad' for #<A:0x00007f847d8494b0 @A="************************************"> (NoMethodError)
# Note that the "#<A:0x00007f847d8494b0 @A="************************************">" part is 65 chars long.
test = test = A.new("*" * 37)
test.dsad # undefined method `dsad' for #<A:0x00007fa8c38299c0> (NoMethodError)
🔗 ローカル開発ガイドの更新
つっつきボイス:「Shopifyの人によるプルリクです」「Railsガイドの更新は地味にありがたい👍」「古い記述があるとハマったりしますよね」「RailsガイドにGitHub CodespacesやVS Code Remote Pluginのことが書かれるようになった↓」
# guides/source/development_dependencies_install.md#L14
-The Easy Way
- ------------
+Other Ways to Set Up Your Environment
+-------------------------------------
-The easiest and recommended way to get a development environment ready to hack is to use the [Rails development box](https://github.com/rails/rails-dev-box).
+If you don't want to set up Rails for development on your local machine you can use Codespaces, the VS Code Remote Plugin, or rails-dev-box. Learn more about these options [here](https://guides.rubyonrails.org/contributing_to_ruby_on_rails.html#setting-up-a-development-environment).
参考: Development Dependencies Install — Ruby on Rails Guides
参考: Rails コア開発環境の構築方法 - Railsガイド
「GitHub Codespacesが実用的に使えるならその方がいいかも」「環境作りに慣れてない人が即作業できるのがいいですよね」
🔗Rails
🔗 Turbo Frame
- 元記事: Turbo Frames とは何か?
つっつきボイス:「今日のWebチーム内発表で触れられていたドキュメントです」「Turbo Frameについてとりあえず概要を知っておくにはよさそう」「記事にもあるように、特定の専用タグで宣言した部分をライブラリで動的に更新していくという昨今のフロントエンドでお馴染みのパターン↓:」「以前のTurbolinksよりはずっと読みやすいし、個人的にはビューを生で使うよりも好き👍」
参考: Turbo Handbook
<!-- GET /posts/1 -->
<body>
<h1>記事詳細</h1>
<turbo-frame id="post_1">
<form action="/posts/1" method="post">
<div><input name="title" type="text" value="記事タイトルが入ります" /></div>
<div><textarea name="body">記事内容が入ります
(編集をクリックすると id="post_1" の部分が書き換わります)</textarea></div>
<button type="submit">更新</button>
</form>
</turbo-frame>
<turbo-frame id="comments" src="/posts/1/comments">
読み込み中。ここに記事コメントが入ります。(遅延読み込み)
</turbo-frame>
</body>
🔗 ruby-on-whales: Rails開発用Docker環境ジェネレータ
つっつきボイス:「先週のウォッチで紹介したEvil MartiansのDocker+Railsの更新記事↓(ウォッチ20220328)で紹介されていたEvil Martians製のツールです」
「なるほど、Docker環境のオプションを対話的に入力するとDocker関連ファイルを生成してくれるのね↓」「まだ動かせてませんが今度試してみます」
「こういう対話型ジェネレータでいいんじゃないかという気持ち」「カスタマイズするときの手間は一緒かもしれないけど、最初の一歩を踏み出しやすくするのはいいですね👍」
つっつき後に手元で動かしてみました↓。まだRedisのオプションなどは含まれていないので、ruby-on-whalesには今後も手を加えそうな気がしています。
$ bundle exec rails app:template LOCATION='https://railsbytes.com/script/z5OsoB'
👋 Welcome to interactive Ruby on Whales installer 🐳.
Make sure you've read the guide: https://evilmartians.com/chronicles/ruby-on-whales-docker-for-ruby-rails-development
Which Ruby version would you like to use? (Press ENTER to use 3.1.0)
Which system package do you want to install? (Press ENTER to continue)
Which database adapter do you use? (Press ENTER to use sqlite3) postgresql
Which PostgreSQL version do you want to install? (Press ENTER to use 14) 14
Which Node version do you want to install? (Press ENTER to use 16, type 'n/no' to skip installing Node) 16
Which Yarn version do you want to install? (Press ENTER to install the latest one)
create .dockerdev/Dockerfile
create .dockerdev/compose.yml
create dip.yml
create .dockerdev/.bashrc
create .dockerdev/.psqlrc
create .dockerdev/README.md
warn 📝 Important things to take care of:
- Make sure you have `ENV["RAILS_ENV"] = "test"` (not `ENV["RAILS_ENV"] ||= "test"`) in your test helper.
- Don't forget to add `url: ENV["DATABASE_URL"]` to your database.yml
info ✅ You're ready to sail! Check out .dockerdev/README.md or run `dip provision && dip up web` 🚀
「お、ruby-on-whalesのリポジトリにterraforming-railsというツール↓のリンクもある」「あ、それはHashiCorpのTerraformではなくてEvil Martiansの各種ツールコレクションとサンプルの置き場のようです」「惜しい、Terraformのtfファイルのジェネレータとかではないのね」「少々紛らわしいですが、Evil Martiansが2019年にRailsConfで登壇したときのタイトル↓をもじったのかなと想像してます」「本来の意味のテラフォーミングか」
terraform: {他動} : 天体の地表と大気を地球と同じように変化させ、居住可能にする。
🔗 HerokuでRails起動時間を半分にするコツ(Ruby Weeklyより)
つっつきボイス:「Heroku向けの小ネタ記事です」「labs:enable build-in-app-dir
を指定するとBootsnapがHerokuで効くようになる、なるほど」「Bootsnapが効けば速いでしょうね」「自分はローカルのDocker環境でBootsnap止めることが多いけど」
heroku labs:enable build-in-app-dir -a <APP_NAME>
🔗 scientist gemでクリティカルなコードパスをリファクタリングする(Ruby Weeklyより)
つっつきボイス:「このscientistというgemはずうっと前のウォッチでちょっとだけ触れました」「記事ではHEY.comで使ったとありますね」
「何をするgemですか?」「Rubyのクリティカルパスのリファクタリングとありますね」「そうそう、scientistはGitHub公式でした」
「use
とtry
にそれぞれ変更前と変更後のコードを渡してrun
で実行すると、両者が食い違うときにエラーになるということみたい↓」
# 同リポジトリより
require "scientist"
class MyWidget
def allows?(user)
experiment = Scientist::Default.new "widget-permissions"
experiment.use { model.check_user?(user).valid? } # old way
experiment.try { user.can?(:read, model) } # new way
experiment.run
end
end
「コンテキストを指定したりできるのね↓」「実際のデータとコードで動作を比較できるということか」
# 同リポジトリより
science "widget-permissions" do |e|
e.context :user => user
e.use { model.check_user(user).valid? }
e.try { user.can?(:read, model) }
end
「以下の記事あたりを見ると↓、大規模なリファクタリングとかをしたときに本当に振る舞いが変わらないのかをproductionのリクエストを流してチェックできるようですね」「GitHubのような大規模なサービスだとscientistのようなツールが欲しくなりそう」
参考: Scientist gemについて調べた - Qiita
参考: Scientist: Measure Twice, Cut Once | The GitHub Blog
🔗 その他Rails
つっつきボイス:「よくある記事かなと思いつつ拾ってみました」「Rubyのアップグレードは大変ではないけど、結局gemのアップグレードが大変なんですよね」「そうそう」
前編は以上です。
バックナンバー(2022年度第1四半期)
週刊Railsウォッチ: RubyKaigi 2022開催情報、RDB参考資料、DNSのHTTPSレコードほか(20220329後編)
- 20220328前編 Evil MartiansのDocker+Rails記事が大幅更新、Railsガイドが電子書籍でほか
- 20220309前編 Crystal言語作者がRubyを愛する理由、TypeScript 4.6リリースほか
- 20220308前編 英国政府サイトで使われるRailsアプリ、pg-oscとPercona Toolkitほか
- 20220301後編 Ruby標準のCSVライブラリは優秀、if代入のコーディングスタイル、rambulanceほか
- 20220228前編 dartsass-railsがリリース、webpack-mergeツール、Rubyが29歳にほか
- 20220222後編: 端末文字幅とRubyのreline、SQLのプリペアドステートメント、Terraformほか
- 20220221前編 orderでコレーション指定をサポート、awesome_nested_set、GitHub Copilotほか
- 20220216後編 Bundler自身のバージョンロック機能、gem署名メカニズムの提案ほか
- 20220214前編 Rails 7.0.2の改修内容、receipts gemでレシートを作成ほか
- 20220209後編 Rubygems.orgのAPIキーに権限スコープが追加、RailsのDBパフォーマンス改善ほか
- 20220208前編 Rails 6.1を7.0にアップグレードしてみた、PostgreSQLでジョブキューほか
- 20220201後編 Rubygems Adoptionフォームが開設、JetBrains Gateway、NGINX Unitほか
- 20220131前編 Sidekiqが10歳に、BuildKiteのテストを高速化、フィーチャーフラグほか
- 20220126後編 Rubyコンパイラの歴史動画、RubyのWebAssembly対応進む、ぼっち演算子の注意点ほか
- 20220124前編 Webpackerが公式に引退宣言、『Everyday Rails』日本語版がRails 7に対応ほか
- 20220118後編 Ruby 2.5〜3.1ベンチマーク、Opal 1.4、JRubyが20歳に、2022年のCSSほか
- 20220117前編 rails-ujs->Turboアップグレードガイド、RubyとWeb Componentsほか
- 20220112 Rails 7をRuby 3.1で動かす、クックパッドのRuby 3.1解説記事、Rails 6->7更新ほか
今週の主なニュースソース
ソースの表記されていない項目は独自ルート(TwitterやはてブやRSSやruby-jp SlackやRedditなど)です。
週刊Railsウォッチについて
TechRachoではRubyやRailsなどの最新情報記事を平日に公開しています。TechRacho記事をいち早くお読みになりたい方はTwitterにて@techrachoのフォローをお願いします。また、タグやカテゴリごとにRSSフィードを購読することもできます(例:週刊Railsウォッチタグ)