- Ruby / Rails関連
週刊Railsウォッチ: Railsで「Read Model」を使う、Ruby Prize 2021受賞者決定、pru gemほか(20211201後編)
こんにちは、hachi8833です。TechRachoのアドベントカレンダー2021が始まる季節になりました。
🔗 Rails
🔗 Read Model
つっつきボイス:「TechRacho翻訳記事でお世話になっているArkencyさんの記事です」「ざっと見たところ、複雑なJOINをするようなデータを毎回Active Recordで取り出したりする代わりに、よく使うデータをRead Modelというもので共通化している感じかな」「広義のFacadeパターンのような趣ですね: 自分はこういうふうに複雑なものをうまく共通化するのは割と好き❤️」「そうそう、よく使うクエリ結果を取り出すFacadeみたいな感じですね」「それにRead Modelという呼び方を与えたということでしょうね」
# 同記事より
ApplicationRecord.transaction do
booking = Booking.create!(params)
CalendarReadModel.handle_booking_created(booking)
end
「ちなみに自分はそういうときにデータベースVIEWを使いたい方です」「例の記事で推している方法ですね↓」
「上のRead Modelみたいなもので仮にActiveRecord::Relation
を不用意に返してしまうと、他の開発者がすぐそこにスコープを追加し始めて壊れたりするんですよ」「そうそう、とてもありがちですよね」
「ActiveRecord::Relation
を返す共通化モデルの中でJOIN済みだったものを、知らずにJOINしてしまって結果がおかしくなるというのはありがちな事故」「そうそう、そもそもJOINしなくていいように作ったはずのものだったのに、それに気が付かずにJOINされてしまうという」
「書いた自分すら後でそういうことをやりかねないので、安全と安心のためにもデータベースVIEWを作るのがいいよと各所で普及に努めてます: データベースVIEWにしておけば、たとえばunscope
されても問題が生じなくなるのが嬉しい」「ですよね」
参考: unscope
-- ActiveRecord::QueryMethods
「ORDER BYとかWHEREで絞り込むぐらいはRead Model的なもので共通化してもいいと思うんですけど、そのモデルで何をやってよくて何をやってはいけないかを厳密に定義するのは結構悩ましい問題ではある」「そういうのを考えるとデータベースVIEWにするのがいいという結論に落ち着きそうかな」
「記事のRead Modelは、ActiveRecord::Relation
を返さないようにすれば何も気にしないで使ってもよいものですね👍: その代わり返す結果が巨大だとメモリを大量に消費しますが」「そうそう」「もっともCQRS(コマンドクエリ責務分離)↓の文脈ではActiveRecord::Relation
を返すことはしなさそうですけどね」
🔗 HanamiとRailsの違いがわかる図
つっつきボイス:「久しぶりのHanami記事ですね」「Hanamiの公式ブログ記事にあったRailsとHanamiのアーキテクチャ比較図がよかったので取り上げてみました」「なるほど、RailsでRoutesから直接コントローラのアクションを呼ぶとか、そこからビューやヘルパーを呼び出すとかはおなじみの部分」「HanamiはモデルのところがPersistanceになってる」「こういう比較の図があるといいですね: Railsを知るにもよさそう👍」
「以前Hanamiを少しやってみたことがあるんですが、RailsだったらこうなのにHanamiは何でこうなってないんだろうみたいなところで悩みました」「もう自分たちはすっかりRailsに慣れているから最初はそうなるでしょうね」「当時こういう図があったらな〜」「自分たちがRailsという圧倒的に複雑なフレームワークに慣れてきた分、よりシンプルなHanamiを理解するのに時間がかかるというのはありそう」「それはあるかもです」
🔗 Rails Tutorial(英語版)の更新
- 元記事: Eager Loading and the N+1 Query Problem | Learn Enough News & Blog
- 元記事: Avoiding session replay attacks in Rails | Binary Solo
つっつきボイス:「この間自分が英語版Rails Tutorial(以下Rails Tutorial)の更新を確認したときに、N+1クエリ問題とsessino replay攻撃とsession fixation攻撃への対応がRails Tutorialに反映されたことを知りました: 上はRails Tutorialの更新部分から参照されていた2本の記事です」「お〜なるほど」「それぞれの更新に関連する演習問題もいくつか追加されていました」「よく大学の教科書で『第x章のy節にあるzを修正せよ』というような解答なしの演習問題が付いていたりしますけど、ちょうどそんな感じですね」
なお、上記2記事の中でもRails Tutorialが対応済みであることについて言及しています。
「Railsを学ぶ人はまずRailsチュートリアルを最後まで走り抜けて一度ちゃんと動かすことが大事ですね: N+1クエリ問題はその後で学んでも大丈夫👍」「そうですね」
「2本目の記事はsession replay攻撃に関するもので、Rails Tutorialでもログインとログアウトの前後にsession_reset
を追加するように更新されていました」「そうそう、基本的な処置ですね: session_reset
を追加するのはRailsガイドにも載っています↓」
参考: Rails セキュリティガイド - Railsガイド
上述の変更内容は今後Railsチュートリアルにも反映される予定です。
「Railsチュートリアルは教育目的なのであえて認証機能を手作りしていますけど、最初からDeviseを使うとマジックが増えて初学者につらくなってしまうからでしょうね」「チュートリアルでいきなりDevise使ったらマジックオブマジックになっちゃいそう😆」「ちなみにRailsチュートリアルの本文では認証ライブラリとしてDeviseを推しています」
🔗Ruby
🔗 Ruby 3.1のMatchData\#match
とMatchData\#match_length
つっつきボイス:「なるほど、MatchData
オブジェクトのmatch
でキャプチャグループを取り出したりmatch_length
でキャプチャ文字列の長さが取れるようになったのね」「Ruby 3.1は新機能を控えめにするということですが、こういう機能も入るんですね」
# 同記事より
result = /\$(?<dollars>\d+)\.(?<cents>\d+)/.match("$1.95")
#=> #<MatchData "$1.95" dollars:"1" cents:"95">
result.match(0)
#=> "$1.95"
result.match(1)
#=> "1"
result.match(:dollars)
#=> "1"
result.match(:cents)
#=> "95"
result.match_length(:cents)
#=> 2
🔗 Primitive.mandatory_only?
でRuby組み込みメソッドを高速化
- Use `Primitive.mandatory_only?` for `Time.at` · ruby/ruby@2a3d5d6
- Use `Primitive.mandatory_only?` for `Array#sample` · ruby/ruby@a24eeee
つっつきボイス:「ruby-jp Slackでたまたま見かけたんですが、Rubyの組み込みメソッドで上のような改修をやってくれる方を気長に募集しているそうです」「どれどれ、RubyのPrimitive.hoge
などを使っている組み込みメソッドで、キーワード引数のすべてにデフォルト値がある場合に、そのメソッドがキーワード引数なしで呼ばれると少し遅くなる、へ〜」「iSeqレベルの話なので細かそう」「以下のようにPrimitive.mandatory_only?
を使って変更することで、キーワード引数なしで呼び出しても遅くならないようにできるのね: 小さな改修でも呼ばれる回数が多ければ改善は大きそう」「貢献するチャンスですね」
# 2a3d5d6より
# timev.rb#L270
def self.at(time, subsec = false, unit = :microsecond, in: nil)
- Primitive.time_s_at(time, subsec, unit, Primitive.arg!(:in))
+ if Primitive.mandatory_only?
+ Primitive.time_s_at1(time)
+ else
+ Primitive.time_s_at(time, subsec, unit, Primitive.arg!(:in))
+ end
end
後で気づきましたが、以下のコミットログに詳しく書かれています。
🔗 Rubyコンパイラのリスト(Ruby Weeklyより)
つっつきボイス:「以下の記事↓を翻訳させていただいたShopifyのChris Seatonさんが、Rubyのコンパイラにどんなものがあるかを調べてみたそうです」「いろんなコンパイラやJITがあるな〜」「@tendeloveさんのTenderJITもありますね」「YJITはリストの下の方に載ってる」「こういうサーベイをやれるところがShopityの強さですね」
🔗 pru: コマンドラインでRubyを手軽にパイプでつなぐ(Ruby Weeklyより)
つっつきボイス:「これは?」「以下みたいにpru
を呼び出すことでRubyをsedやawk的なフィルタとして手軽に使えるようにするそうです」「お〜なるほど、Rubyを-e
オプションで使おうとすろとPerlのperl pe
よりコマンドラインが長くなりがちなので、なかなか便利そう👍」「pru -i Gemfile 'sub /ruby/, "foo"'
でperl -i
的なインライン置換もできるんですね」
# 同リポジトリより
# count letters of each line
ls -1 | pru size
# select lines longer than five letters
ls -1 | pru 'size > 5'
# 2nd to last character
ls -1 | pru self[2..-1]
「このpru
のシングルバイナリ版が欲しいですね: gem install
できない環境でも使えるようになるので」「それ欲しいです」「例のBusyBox↓にpru
もで入ってくれたらとても嬉しい」「BusyBoxはよく使うコマンドがシングルバイナリになっているんでしたね」
🔗 その他Ruby
RT °rubycitymatsue: Ruby Prize winners released!
congratulations! 🎉https://t.co/5GIJSO3PZl#rubyprize#rubyworld— Yukihiro Matz [en] (@matz_translated) November 19, 2021
つっつきボイス:「今年のRuby PrizeはYJITでRubyに貢献したShopifyのMaximeさんでしたね」「YJITをここまで作り上げたMaximeさんとShopifyの人たちはホント凄い」「MaximeさんがPhD論文で提案したBasic Block Versioning(BBV)をRubyのYJITに応用したそうです」
おお、ついに改訂版チェリー本の先行発売が始まったようです!今ゲットすれば著者より早く読めます!!(僕のところにはまだ届いてないw)お近くの方は書泉ブックタワーさんへGO!💨 https://t.co/FNtMqHoepE
— Junichi Ito (伊藤淳一) (@jnchito) November 22, 2021
「チェリー本の改訂第2版がいよいよ先行発売開始🎉」
🔗クラウド/コンテナ/インフラ/Serverless
🔗 厚労省の「偽装請負」に関する疑義応答集の解説(Publickeyより)
- 元記事: アジャイル開発の外部委託が「偽装請負」だと疑われないためにすべきこと、厚労省が公表した疑義応答集を読み解く(前編)。Agile Japan 2021 - Publickey
- 元記事: アジャイル開発の外部委託が「偽装請負」だと疑われないためにすべきこと、厚労省が公表した疑義応答集を読み解く(後編)。Agile Japan 2021 - Publickey
- 労働者派遣事業と請負により行われる事業との区分に関する基準(37号告示)関係疑義応答集|厚生労働省
つっつきボイス:「Agile Japan 2021でIPA専門委員の弁護士が厚労省の関係疑義応答集を解説してくれたのを記事にしたものですね: 自分の理解が概ね合っていたことがこの記事で確認できました」
参考: Agile Japan 2021 | The Heart of Agile
「そういえばBPSは客先常駐を基本的に行っていませんけど関連はあるんでしょうか?」「発注元が受注先の指揮系統を通さずに受注先の作業者に直接指示を出すことが違法になるので、常駐やリモートの有無にかかわらず関連はあります」「なるほど」「発注元が受注先の作業者に直接指示を出すなら派遣の形にする必要があります(発注前に作業者を面談・試験したりするのは派遣でも違法です)」
「いわゆる準委任型の開発を受ける側はこういう点に気をつける必要があるんですが、受注側が守りに入りすぎると今度はアジャイル開発のよさが失われてしまって、たとえばアジャイルでよくあるスタンダップミーティングすらできなくなってしまったりします」「あ〜たしかに」
「話そのものは新しくはありませんが、これまでグレーになりがちだった部分についてIPAの弁護士が事例込みで詳しく解説してくれたのはありがたい」「ちゃんと読んでおこうっと」
後編は以上です。
バックナンバー(2021年度第4四半期)
週刊Railsウォッチ: フォームヘルパーの改修、Railsの監査ログgem比較、DHHとimport-mapほか(20211129前編)
- 20211116後編 Ruby Struct入門、書籍『進化的アーキテクチャ』、AWS Web問題集ほか
- 20211115前編 Rails 7がRuby 3.1のClass#descendantsに対応、GitHub Issue風ファイルアップローダほか
- 20211110後編 JSON.parseの機能、Opal 1.3、async gem、Linuxコマンドチートシートほか
- 20211102後編 2021年度Rubyアソシエーション開発助成、Rails REST APIレベルで楽観的ロックほか
- 20211101前編 Rails 7アセットパイプライン解説記事、ロジックをapp/operatorsで整理ほか
- 20211026後編 YJITがRuby 3.1向けにマージ、ripperのドキュメント化、crontabの罠ほか
- 20211025前編 insert_allやupsert_allのタイムスタンプ自動更新、rails/contextsにロジックを置くほか
- 20211019後編 ruby/debugをChromeでリモートデバッグ、Rubyアプリの最適化ほか
- 20211018前編 Railsリポジトリで進行中のPropshaft、inverse_ofを自動推論ほか
- 20211012後編 Ruby 3.1にYJITマージのプロポーザル、Rubyのmagic historyメソッド、JSのPartytownほか
- 20211011前編 ServerTimingミドルウェア追加、paramsで数値キーを許可、Railsで多要素認証ほか
- 20211006後編 ruby/debug 1.2.0リリース、Railsにはthorが入っている、tendejitほか
- 20211004前編 Rails 7でbyebugがruby/debugに変更、GitHub Codespacesをサポートほか
今週の主なニュースソース
ソースの表記されていない項目は独自ルート(TwitterやはてブやRSSやruby-jp SlackやRedditなど)です。
週刊Railsウォッチについて
TechRachoではRubyやRailsなどの最新情報記事を平日に公開しています。TechRacho記事をいち早くお読みになりたい方はTwitterにて@techrachoのフォローをお願いします。また、タグやカテゴリごとにRSSフィードを購読することもできます(例:週刊Railsウォッチタグ)