- Ruby / Rails関連
週刊Railsウォッチ: Ruby 3.1にYJITマージのプロポーザル、Rubyのmagic historyメソッド、JSのPartytownほか(20211012後編)
こんにちは、hachi8833です。
🔗Ruby
🔗 YJITマージのプロポーザル(Ruby Weeklyより)
つっつきボイス:「YJITをRubyにマージしようというプロポーザルにMatzが+1付けていました」「YJIT凄い」「Shopifyのような強い会社が集中的に作るのでないと短期間でマージ可能なところまでなかなかこぎつけられないでしょうね」「たしかに」「Shopifyが社内で使っているというのは、GitHub内部で使われているというのに匹敵するぐらい大きなアピールになりそう」「MJITを手掛けてきたk0kubunさんも早速YJITを詳しくチェックしていますね」「YJITマージ、いい流れだと思います👍」
「YJIがマージされたら3.1.0-preview1を出すとnaruseさんがコメントしてました」「お〜」
「MJITはプラットフォーム互換性は高いけど効率を上げにくいところがありましたが、YJITの実装はCPUアーキテクチャに依存する分効率を上げやすいようなので、JITの目指す方向としては好ましいかも」「そういえばYJITは対応プラットフォームがまだ少ないとissueの冒頭に書かれていました」「そうそう、MJITはプラットフォーム互換性を優先する設計になっています」
🔗 もっとRubyのマジックを
つっつきボイス:「記事ではproject.1.day.ago
や1_business_day_ago
みたいな書き方をmagic historyメソッドと呼んでいますけど、これは他の言語からRubyに来た人が驚くもののひとつでしょうね」
「project.1.day.ago
みたいな書き方は初めてみたときにちょっと不思議でしたけど、今では普通に使っています」「特に英語圏の人にうれしみがありそう」「英語圏でなくても便利だと思いますよ」「Rubyはこうやって直感的に書けるのが便利ですよね」「記事にもあるように、project.one_day_ago
のようにドットの代わりにアンダースコアでつなげる書き方もできます↓」
# 同記事より
describe "magic history" do
let(:team) { build(:team) }
let(:project) { build(:project, team: team) }
before do
travel_to(Date.parse("Sep 23, 2021"))
end
it "handles date travel correctly" do
expect(project).to receive(:at).with(Date.parse("Sep 23, 2021"))
project.at(Date.current)
end
it "can go back one day" do
expect(project).to receive(:at).with(Date.parse("Sep 22, 2021"))
project.one_day_ago
end
it "can go back two days" do
expect(project).to receive(:at).with(Date.parse("Sep 21, 2021"))
project.two_days_ago
end
it "errors on nonsense" do
expect { project.banana }.to raise_error(NoMethodError)
end
end
「記事ではis_magic_history_method?
というメソッドを書いて、あるメソッドがマジックで生成されたものかどうかを確かめたりしてる↓」「なるほど」「メソッド名をアンダースコアでsplit
して、呼べるかどうかをチェックしてるんですね」「これはたしかにマジック🧙」
# 同記事より
def respond_to_missing?(method_name, include_private = false)
is_magic_history_method?(method_name)
end
def is_magic_history_method?(method_name)
number, duration, time = method_name.to_s.split("_")
return false if NumbersInWords.in_numbers(number).zero?
return false unless duration.in?(%w[day days])
return false unless time == "ago"
true
end
def method_missing(method_name)
super unless is_magic_history_method?(method_name)
number_string, duration, _ = method_name.to_s.split("_")
number = NumbersInWords.in_numbers(number_string)
date = number.send(duration).ago
at(date)
end
「記事では『無用なのはわかってるけどいろいろ楽しい』とあります」「やっぱり楽しさ大事: 自分が普段使っているコードが裏でどのようになっているのかを知るのは、コードを早く書くとかにすぐ役立つわけではなくても、Rubyについてより詳しく知ることができますよね」
🔗 Rubyの整数演算オーバーフローチェックを「スタンプ」で削減する(Ruby Weeklyより)
つっつきボイス:「RubyKaigi Takeout 2021で例のオブジェクトシェイプ↓について発表したShopifyのChris Seatonさんが、今度はTruffleRuby内部にスタンプという概念を導入してVMの整数演算オーバーフローチェックを削減する記事を書いてました」
「TruffleRubyとその中にあるGraalVMの機能を使って最適化しているようですね↓」
def add_stamps(a, b, c)
a = Truffle::Graal.inject_stamp(a, 0xff)
b = Truffle::Graal.inject_stamp(b, 0xff)
c = Truffle::Graal.inject_stamp(c, 0xff)
a + b + c
end
参考: GraalVM
「図の左が最適化前、右が最適化後だそうです」「お〜、右の最適化後は短く並列なパスになってて依存も少なさそう: 左の最適化前は必ず通らなければならない箇所がたくさんありますね」「ざっと見ただけですがいろいろ凄いことやってそう💪」「こういう概念と実装をきちんと解説してくれる人がいるのは頼もしい」
🔗 code2flow: コールグラフのビジュアライズgem(Ruby Weeklyより)
つっつきボイス:「なるほど、呼び出しのパスを解析してこういう感じのコールグラフを生成するんですね↓」「Ruby以外にも複数の言語に対応しているそうです」
Code2flow - a tool to generate call graphs for dynamic programming language. https://t.co/e3DN8XAjSr pic.twitter.com/jDCYrydTUP
— OmbuLabs | The Lean Software Boutique (@OmbuLabs) October 6, 2021
「この種のグラフ生成といえば、Graphvizがもう何十年と使われ続けていますよね」「そうそう、Graphvizは定番: 前職でシェルの呼び出しをGraphvizでこんなふうにビジュアライズしたのを思い出しました」
The new #SAPFioriTools allows visualizing #SAPCAP #CDS file dependencies. You need to install #VSCode extension #Graphviz (dot). The extension is also able to preview your own files (also hexagon shape) and download it as #SVG. See https://t.co/3RPdAJbaAa pic.twitter.com/eAQFO0mfJd
— Holger Schäfer (@hschaefer123) September 14, 2021
「ところで、Graphvizで生成したグラフは複雑になってくると密集して手に負えなくなってきますね」「そうそう、仕方ないとは思いますけど」「このcode2flowはなかなかいい感じに出力できてるように見える」「おや、code2flowはGraphvizを使わずにやっているのかと思ったら、インストール要件にGraphvizが書かれている」「やっぱりGraphviz使ってるんですね」
🔗クラウド/コンテナ/インフラ/Serverless
🔗 書籍『AWSコンテナ設計・構築[本格]入門』
つっつきボイス:「はてブで話題になっていました」「このコンテナはどのコンテナを指しているのかな?」
「Amazonのページなども見た限りでは、ECSやFargateのコンテナを対象にしていて、Lambdaのコンテナは含まれていないように見える」「なるほど、コンテナといってもいろいろあるんですね」「FargateもECSのサービスのひとつなので、おそらく広義のECSのコンテナを指しているんじゃないかな」
参考: Amazon ECS(Docker コンテナを実行および管理)| AWS
参考: AWS Fargate(サーバーやクラスターの管理が不要なコンテナの使用)| AWS
🔗JavaScript
🔗 Partytown
“今Partytownがヤバい。JavaScript Sandboxの未来はどっちだ?” https://t.co/7sgvbixJOv
— 徳丸 浩 (@ockeghem) October 7, 2021
つっつきボイス:「これもはてブで話題になっていました」
「記事冒頭は、外部のスクリプトを手元ではなるべく隔離された環境で動かしたい、しかしscript
タグで読み込むと全コンテキストを触れるので強すぎる、それを避けるにはiframe
で読み込むことで実質コンテナ的に動かせる、またはWeb Workerで動かせばメインのコンテキストから分離できる、という感じの流れですね」「ふむふむ」
「ShadowRealm↓というプロポーザルは、1個のJS実行系の中にShadowRealmを置いてグローバルオブジェクトに触らせないようにするというものらしい」
// 同リポジトリより
declare class ShadowRealm {
constructor();
importValue(specifier: string, bindingName: string): Promise<PrimitiveValueOrCallable>;
evaluate(sourceText: string): PrimitiveValueOrCallable;
}
「ShadowRealmは同一プロセス内で動くのでSpectre↓のような攻撃が心配されると書かれてるけど、CPUの脆弱性まで気にするときりがなさそう」「Spectreは脆弱性の名前なんですね」
参考: Google Developers Japan: Spectre の影響を受けないウェブを作るための概念実証について
「Web Workerは別スレッドで動くので比較的わかりやすくて、ホスト側と非同期メッセージ通信もできるしプロセス分離も可能になる、その代わりDOMプロパティへの同期アクセスは難しい、たしかに」
「Web Workerはセキュリティ的には望ましいけど使いにくいということでしょうか?」「Web Workerは独自のコンテキストで動くもので、非同期メッセージ通信しかできないので、メインスレッドにあるDOMを直接触るのが難しいんですよ: なのでメインスレッドのDOMを更新するような処理はWeb Workerに投げにくい」「DOMを触らない純粋な計算処理ならWeb Workerでやれるけど、DOM更新には不向きということなんですね」
「WebAssemblyはメモリも別環境で動いて同期アクセスも可能なのか、へ〜」
「そしてPartytown: サードパーティのコードを別プロセスで動かしたいけどブラウザのDOMにもアクセスしたい、document.body.clientWidth
みたいなものにアクセスしたくても、同期DOMを前提とするライブラリはそのままではアクセスできない」「ふむふむ」「Partytownではそのために同期的なXMLHttpRequest呼び出しを使うのか!なつかしいものが登場した」
参考: XMLHttpRequest - Web API | MDN
「Partytownでは、Worker内に仮想的なDOM環境を置いてプロパティアクセスを同期的なXMLHttpRequest呼び出しに変換する、でもそのままではXMLHttpRequestでURLにアクセスできないのでService Workerでインターセプトする: これはなかなかのハックですね」
🔗 Web WorkerとService Worker
「Web WorkerとService Workerの違いがわかってなかった...」「Web Workerはスレッド的に動作する普通のワーカーで、Service WorkerはMDNにもあるようにイベント駆動のプロキシサーバー的なワーカー」「なるほど」「Service Workerは使ったことがありませんが、イベントフックに似ているかも」
参考: Web Worker の使用 - Web API | MDN
参考: サービスワーカー API - Web API | MDN
「JavaScriptの呼び出しの多くが非同期に向かう中、残された同期的なXMLHttpRequest呼び出しを使ってPartytownを実現しようとしているということかなと思いました」「なるほど」「その呼び出しをうまく隠蔽して、あたかもWeb WorkerがDOMに同期アクセスしているかのように振る舞わせることができる、そしてサードパーティのJSからDOMへのマッピングを行う部分でアクセス制御可能なので、そこで分離しようと思えばできる、という感じ」
🔗 古い機能がよみがえるとき
「こういう無理矢理感は面白いですね😆」「こんなふうに、昔登場したけどあまり使われていなかった機能が、後に思いもよらぬ方法で使われるようになってよみがえるというのは言語の歴史でときどきありますね」「たしかに」「XMLHttpRequestも実はそうで、Ajaxでとても有名になりましたけど、もともとの仕様策定でこういう使い方は想定されていなかったはず」「へ〜!」「その意味でAjaxは既存技術の組み合わせに過ぎないとも言えますね」
参考: Ajax - Wikipedia
🔗CSS/HTML/フロントエンド/テスト/デザイン
🔗 SPAセキュリティ入門
PHPカンファレンス2021の資料です / “SPAセキュリティ入門~PHP Conference Japan 2021” https://t.co/7B7exX2kWB
— 徳丸 浩 (@ockeghem) October 3, 2021
つっつきボイス:「PHPカンファレンス2021やっていましたね」「徳丸先生のプレゼン冒頭でTechRachoの翻訳記事が引用されていると知りました↓」「よくランキングに上がってるLocal Storage記事ですね」
「結論としては、Local Storageだから即危険とは限らないそうです↓」「JWTが当初と違う使われ方をするようになってきたのはしょうがないのかなという気もしますけど」「そうかもですね」「JWTは開発者にとっては使いやすいんですよ、それもあってついLocal Storageに入れてしまうのかもしれませんね」
🔗 その他HTML
HTTPのステータスコードに応じた猫の画像を返すサイト。画像にはちゃんと意味がある。個人的には200と401, 414, 418 がお気に入り。https://t.co/QAcdF464JP
— 新山祐介 (Yusuke Shinyama) (@mootastic) October 7, 2021
つっつきボイス:「お楽しみ画像です」「お〜ネコ画像🐈⬛」
「202 Accepted」「304 Not Modified、そう来たか」「406 Not Acceptable、ネコ嫌がってるのが感じ出てる😆」「408 Request Timeout」「414 Request-URL Too Longは昔出回ってたコピペ画像ですね」「599 Network connect timeout errorツボった」「5xx系にあるとは思わなかった」「418 I'm a teapotは有名なジョークプロトコルですね↓」「HTTPステータスコードの数だけネコ画像集めたの凄い」
参考: Hyper Text Coffee Pot Control Protocol - Wikipedia
後編は以上です。
バックナンバー(2021年度第4四半期)
週刊Railsウォッチ: ServerTimingミドルウェア追加、paramsで数値キーを許可、Railsで多要素認証ほか(20211011前編)
- 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ウォッチタグ)