9
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Node.jsやPythonにはある◯◯がRubyにはない。そんなのはAIに作らせりゃいいのだ?

Posted at

まえおき

Playwright というブラウザを自動操作できるライブラリがあるのは知っている方も多いでしょう。公式にはNode.js, Python, C#, Java など主要な言語がサポートされていますが、Rubyはありません。

こういうところにこそ、個人開発で活躍できる場が潜んでいると私は思っているのですが、それは一旦おいといて、「イマドキだったらAIに簡単で作れるじゃん」 なんて発想になる人もいるかもしれません。

本当にそんなことできるんでしょうか?

過去に PuppeteerというNode.jsライブラリをRubyに移植した ことがあるオジサンが、それとなくコーディングエージェントを使って実験&考察してみます。

愚直に「PuppeteerをRubyのGemにしてくれ」と言うと何が起きるのか

さすがに一言投げるだけではまともなものが出てこないのは明白なので、Gemini 3.0あたりに軽く要件定義させたものを渡します。

Puppeteerというブラウザを自動操作するNode.jsのライブラリをRubyでも使えるようGemとして実装したい。

Example

import puppeteer from 'puppeteer';// Or import puppeteer from 'puppeteer-core';
...(略)...

PuppeteerのGitHubリポジトリのREADMEに書かれているこのようなコードが実行できるレベルの移植をまずはおこないたいのですが、コーディングをするエンジニアが何をどのように作ればよいかわかるよう、基本設計書をMarkdown形式で出力してほしい。

CleanShot 2025-12-23 at 23.24.36@2x.png

(中略)

CleanShot 2025-12-23 at 23.24.17@2x.png


なんだかそれっぽいものが出てきました。

既に世の中にあるライブラリをパクってるだけのような設計なので、あえて既出のライブラリとは異なる要求を与えてみます。

  • 非同期処理を行う部分はスレッドベースのconcurrent-rubyではなくFiberベースのsocketry/async を使用したい。
  • WebDriver BiDiを使用してFirefoxを自動操作できるようにしたい。CDP, Chromeの自動操作はスコープ外とする。

CleanShot 2025-12-23 at 23.36.43@2x.png

(中略)

CleanShot 2025-12-23 at 23.37.29@2x.png


╭─── Claude Code v2.0.76 ───────────────────────────────────────────────────────────────────────────────────╮
│                                                    │ Tips for getting started                             │
│                Welcome back Yusuke!                │ Ask Claude to create a new app or clone a repository │
│                                                    │ ──────────────────────────────────────────────────── │
│                     * ▐▛███▜▌ *                    │ Recent activity                                      │
│                    * ▝▜█████▛▘ *                   │ No recent activity                                   │
│                     *  ▘▘ ▝▝  *                    │                                                      │
│                                                    │                                                      │
│      Opus 4.5 · Claude Max ·                       │                                                      │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯

───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
> あなたはRubyでGem開発を特異とするエンジニアです。PuppeteerというNode.jsのライブラリをRubyに移植したいので、添付の設計に
  従って移植を進めてください. [Pasted text #1 +310 lines] 
───────────────────────────────────────────────────────────

Gemini 3.0からもらった設計書をまるっと貼ります。

滑り出しは順調です。単純作業なので当たり前ですね。

CleanShot 2025-12-23 at 23.42.06@2x.png

つづいて、それぞれのクラスが作られ始めました。

CleanShot 2025-12-23 at 23.44.04@2x.png

この調子なら、15分もすれば、なんかFirefoxを起動して BiDiプロトコルを使ってブラウザが動くコードは出来上がるかもしれません。

CleanShot 2025-12-23 at 23.50.53@2x.png

AIが15分で作ったライブラリ、ちゃんと動くの?

AIコーディングでは、計画→実装→アサーション を繰り返すことで品質を上げていく必要がありますが、そのアサーションはどうするか?

さきほどのプロンプトを見ると、動作検証用のコードは一応作ってくれていました。しかしどうも動かしている形跡がありません。

CleanShot 2025-12-23 at 23.49.25@2x.png

実際にサンプルを動かしてください

と指示をしてみましょう。

CleanShot 2025-12-23 at 23.54.31@2x.png

CleanShot 2025-12-23 at 23.54.45@2x.png

CleanShot 2025-12-23 at 23.54.59@2x.png

CleanShot 2025-12-23 at 23.55.51@2x.png

おっと、socketry/asyncベースのWebSocketを使うのを諦めて、websocket-driverを使い始めました よ。

...で、結局何が起こるのか

結論から言うと、永遠にライブラリは完成しません。

理由は明らかで、タスクの粒度が粗すぎるからです。かりに人間に依頼するとしても「Node.jsのこのライブラリをRuby Gemにして」で開発できる人はいません。そこはAIも同じです。

なぜ人間はAIには丸投げしたくなるのでしょうね。

人間が知らないといけなかったこと1: 言語特有の機能のポーティング

Gemini 3.0は実はうまく問題提起をしてくれていました。

特に「非同期処理(Promise vs 同期)」の部分や、特定のライブラリ選定についてより詳しく掘り下げたい箇所はありますか?

と。ただ、そもそもこれが何を意味しているのかわからないと、「そうだね」と従うしかない状況になります。

  await Promise.all([
    page.waitForNavigation(),
    page.click('.search'),
  ]);

JavaScriptでは↑のように async/awaitを使って非同期プログラミングを気持ちよ~く書くことができますが、他の言語で同様に気持ちよく書けるのはDartくらいです。

PythonのasyncioでもKotlinのcoroutinesでも、どこのスレッドでジョブ実行のループが回っているのか意識しないといけないし、Rubyに至っては言語仕様にasync/await相当のものがありません。かろうじてサードパーティのライブラリであるsocketry/asyncやconcurrent-rubyが存在はしています。

が、これらのライブラリはJavaScriptのasync/awaitでできることがすべてできるのか?同じ動きをするのか?

結局のところ、 https://socketry.github.io/async/guides/best-practices/index.html https://ruby-concurrency.github.io/concurrent-ruby/1.3.6/index.html のようなドキュメントを読んでもその正解にはたどり着かず、GitHubで公開されているソースコードを読むことになります。



Node.jsのasync/awaitの他にもたとえば、PythonのPydanticやデコレータなどもRubyでの代替方法がありません。このあたりはあらかじめ下調べをして、どのような方針を取るべきかを人間の側が把握して判断可能な状況にしておかないといけないのです。

人間が知らないといけなかったこと2: 本家のライブラリと「同じことができる」ことを確かめる方法

人の役に立つようなライブラリを作るのであれば、正しく動くことが不可欠です。

AIが吐き出した「多分動くと思うから...」っていうレベルのコードで成り立っているライブラリは、ビジネスアプリケーションでの利用はまずできませんし、個人開発でも興味本位で1, 2回触られたらいいほうでしょう。

Puppeteerのリポジトリをみてみると、本当にたくさんの単体テストが書かれているのがわかります。

実際に現場で使われるようなライブラリというのは、これほどしっかりテストされている必要があるのです。そして、「Node.jsにある◯◯ライブラリをRubyにポーティングした」と銘打つならば、同じようなテストコードを書く必要があります。

ここもAIにてきとうに「mochaで書かれたテストコードをRSpecに移植して!」では当然に動くテストはできあがりません。

  • そもそもで、Rubyに移植したライブラリでは、どれが正確に再現されないといけないspecなのでしょう?
  • Node.js版のライブラリでは、テスト時にFirefoxの起動部分はモックしているのでしょうか?それとも本当に起動しているのでしょうか?
  • HTTPのサイトに対向する試験をやっているとすると、そのテストHTTPサーバーはいつ起動していつシャットダウンするのでしょうか?それをRSpecではどう書くのでしょうか?

これらの疑問が解消できるくらいの、見本コードが2~3ファイルある状態なら、それを参考にAIコーディングを進めることはできます。ただし、最初の2~3ファイルは人間による試行錯誤や良し悪しの判断が必要です。

人間が知らないといけなかったこと3: 本家のライブラリと同じ動きをしなかった際のデバッグ方法

たとえば

puppeteer.launch(headless: true).then(async browser =>
  const page = await browser.newPage()
  await page.goto('https://developer.chrome.com/')
  await page.screenshot({ path: "screenshot-js.png" })
Puppeteer.launch(headless: true) do |browser|
  page = browser.new_page
  page.goto('https://developer.chrome.com/')
  page.screenshot(path: 'screenshot-ruby.png')

この2つのスクリプトで、出力された画像が3ピクセルずれている!ってなった際に、どうデバッグすればよいでしょうか?Node.jsとRubyのどちらの動きが正しいでしょうか?それはどこて判断できるでしょうか?

実はNode.js版のPuppeteerでは実は公式ドキュメントでデバッグ方法がいくつか紹介されているのですが、このようにRubyにポーティングした際には、何かしらデバッグ用の方法を作り込んで同様のデバッグ手順を確立しておかないと比較ができません。

Puppeteerであれば、Chrome DevTools Protocol (CDP) や BiDi のメッセージログを両言語で出し、JSONのプロトコルメッセージを差分比較するような、実に泥臭いデバッグ環境を構築しておけば、AIコーディングエージェントが自律的にデバッグして修正までやってくれます。

が、このあたりの設計を思いついて用意できるか、は現時点ではAIにおまかせはできず、人間が責任持っておこなう必要があります。

要するに、Node.jsやPythonにはある◯◯がRubyにはない、そんなものを作れるのは人間だけだ。

ライブラリの動きを調査するためのコードを書いてもらうとか、Puppeteerのソースコードの特定のメソッドの内容を解説してもらうなど、用途を絞ればAIの活用はできるでしょう。

しかし、ここまでで書いてきたように、人間が判断しないと正解にたどりつかないものや、人間が先回りして下調べをしておかないといけないもの、がたくさんあります。

正確な判断をする能力というのは一朝一夕に能力は身につくはずもなく、経験と勘の積み重ねによるところが大きいですので、。ポーティングをするにはまずはポーティングを一通り経験してみる必要があります。

ただ、AIは使わないよりは使ったほうがいい

実は、ここ2ヶ月くらいスキマ時間でひたすらAIコーディングでPuppeteerをRubyに移植するのをやってみていました。

過去に https://github.com/YusukeIwaki/puppeteer-ruby を作ったときは手作業で結構がんばって5ヶ月くらいかけて移植したのと比較すると、生産性は格段に向上しています。より正確に言うと、不毛な時間が劇的に減っています

とくに、OpenAI CodexでGPT-5.2を使えるようになってからは顕著で、人間が調べるよりも深い考察で妥当性判断をやってくれるため、無駄にハマって時間を浪費してしまう事がほぼなくなりました。例えば「Node.js版ではundefinedと""の扱いに区別があるけど、Ruby版ではnil一択で、プロトコルレベルで互換性がない」など、人間ではなかなか気づきづらい部分もコードを動かすことなく的確に指摘してくれたりします。

AIエージェントのコーディング風景は見るだけでも勉強になる

これは新しいライブラリを試してみる場合は特にそうなのですが、試行錯誤する過程は見ているだけでも参考になります。「どんな書き方をしたらどんなエラーになる、だからこうしないといけない」という経験を数こなすことで我々は賢くなることができるわけですから、AIエージェントを走らせている間に別のことをやるのは割ともったいないです。

とくに、socketry/async のように少々クセのあるライブラリを攻略したい!って場合にはぜひAIに学ばせてもらうとよいです。

ただ、「見ているだけで」と言っても フィードバックは適切に人間がおこなう 必要はあります。AIの学習データが古いことに起因したものは特にそうで、「 Async::Condition は使わないで、 Async::Promise を使ってほしいです。リファレンスはコレ https://github.com/socketry/async/blob/main/lib/async/promise.rb 」のように 与える文章は支離滅裂でもいいので、別案でやってほしい旨を伝える と、読み解いて書き直してくれます。

まとめ

この1年で、AIコーディングエージェントの精度は格段に向上して一気に実用レベルになりました。ただ、「作りたいものがあるんだよねー」だけでは(そもそもAI関係なく)世の人の役に立つライブラリは作れないので、当然にAIに丸投げしてライブラリを作ることはできません。

AIに学ばせてもらって人間が効率よく経験を積んで、AIコーディングエージェントに効果的な指示を出せるようになれば、Node.jsにあるアレ、Pythonにある便利なアレ、はRubyに効率的にポーティングできるようになります。

世の中の便利なライブラリのRubyへのポーティングは本当に色々勉強になるので、ぜひAIエージェントとともに個人開発してみてください。

image.png

(おまけ: GeminiのNano Bananaに生成させたイメージ画像w)

9
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?