おもしろwebサービス開発日記

Ruby や Rails を中心に、web技術について書いています

続・wkhtmltopdfの次どうするか問題

wkhtmltopdfの次どうするか問題 - おもしろwebサービス開発日記の続き。

上の記事でも書いていますが、令和の今RailsアプリケーションでPDFを生成する基本的な方針としては次の2択だと思っています。

  • chromeを使ってHTMLからPDFに変換する
  • Thinreports などで直接PDFを生成する

「chromeを使ってHTMLからPDFを生成する」のgemとしてはgroverが有名ですね。だけどこれはruby -> puppeteer -> chromeという構成で、間にnode製のツールであるpuppeteerが挟まっています。

ferrum はrubyから直接chromeを扱うgemなので、これを利用するとnodeが不要になるしメモリ消費量も多少下がるはずだしいいじゃん、と前記事を書いているときは思っていました。しかしferrumはあくまでchromeを操作するのが目的のツールなので「Railsが生成したHTMLからPDFを生成する」ために必要な機能は備えていません。

例えば「RailsでrenderしたHTMLをchromeに食わせてPDFに変換する」部分は自分で書く必要があるし、「HTML中の相対パスで書かれているリンクを絶対パスに変換する」というのも必要になってきます。

なのでferrumだけだといろいろ自分たちで頑張らないといけない部分が多かったのですが、この面倒な部分をやってくれるgem ferrum_pdfが去年くらいからリリースされています。まだ個人的には使えてないですが、@takeyuwebさんは導入したことがあるようです

なのでgroverを使うようなケースであればferrum_pdfを試してみるのがいいかと思っています。

でも本当にこれでいいのかな?

ferrum_pdfを使うにしても結局「chromeを使ってHTMLからPDFに変換する」形式なのでアプリケーションサーバのメモリが心配になるケースがありそうです。その場合は別インスタンスに「HTMLをPDFに変換する専用アプリケーションサーバ」を立ててPaaSSaaSのように運用するのがいいんじゃないかな〜とぼんやり考えています。そうするとメモリ消費量が心配になったときにHTML->PDFの部分だけスケールアウトできるので…。

この手のPaaSSaaS自体は探すといくつかヒットしますが、HTMLを外部サービスに投げたくない場合がほとんどなはず。

カッとなったら作るかもしれませんが直近ではその予定がないので、もし興味のあるひとがいたら作ってもらえると嬉しいです。

gon v6.5.0をリリースした

gonのメンテナになった - おもしろwebサービス開発日記 の続き。

新しいRubyで出るwarningやエラーなど一通り対応できたかな、という状況になったので作者からrubygems.orgにpushする権限をもらってv6.5.0をリリースしました。使ってみてなにかおかしいところあったら教えて下さい。

テストコードが微妙な箇所がまだかなりあるので、今後気が向いたときにほそぼそと直していきます。

gonのメンテナになった

gazay/gon: Your Rails variables in your JS

お手伝い先で使っているので見てみたら最終コミットが4年前でIssueやPRが積み重なっており、CIはTravisCIという状況。メンテされないgemとどう向き合うか。“普通のOSS開発者” willnetさんの取り組み で書いたようにCIをGitHub Actionsに移行するPRを出して作者にメンションするも音沙汰なし、というところで気合を入れて作者にメールをしたところメンテナ(collaborator)にしてもらえました。

seed-doと同様に、新しいRubyやRailsで動かないのをなんとかするくらいのモチベはあるのでできる範囲で頑張っていこうと思います。

ginza.rb 第91回を開催してGumroadについて学んだ

Ginza.rb 第91回 - Gumroadのソースコードを読むぞ - connpass 第91回はOSSになったGumroadコードを読みました。

Gumroad

実際にお金を稼いでいるアプリケーションのコードをOSSにして、外部コントリビュータのPRをうけつつその上で開発を進めるというのは世界的に見てもなかなかユニークな形式なのではないでしょうか。

流石にコード公開前の履歴まではみれないですが、それ以外は特にコードの公開用に体裁を整えた形式が見えないのが潔いなと思いました。コードを眺めるとapp/helpersにビューヘルパーではないヘルパー用モジュールが含まれているのとか、app/modulesがなんでもモジュール置き場になっているのとかにとてもリアルさを感じます。このような負債は多かれ少なかれ歴史のあるアプリケーションには必ず見られるものですが、今後これとどのように付き合っていくのかを外部から見守っていけるのはありがたいところです。

Gemfileをみると数多くのgemが使われているのがわかります。かなり古くメンテナンスが滞っているgemもありますが、恐らく「この便利gemは知らなかった…」というものが1つや2つは見つかるはず。

AIの活用という点でも学べる点は多いです。まずコードを書く方面でLLMを活用しています。.cursorrulesが定義されていたり、devinがPRを作っていたりします。レビューにはCodeRabbitDiamondCursor – BugBotを利用しているようです。

あとはコード中でもLLMを活用しています。koicさんも書いていますが、自然言語で書いた返金ポリシーをLLMに解釈させていい感じにユーザに応じた返金までの期間を算出するのが面白かったです。現状ふつうのプログラミングでは算出が難しいロジックの一部をLLMにまかせて運用工数を短縮する面白い実例なのではないでしょうか。

10年以上の歴史を持つコードであり分量も多いですが、読む価値はあると思います。

次回

次回は8月8日(金)開催で「アプリケーションサーバ」というお題で実施する予定です。この分野だとpumaやunicornが有名ですが、それ以外にも数多くの選択肢があるぞというのを掘り下げていく予定です。

興味のある人は予定を開けておいてください。

Action MailboxをAWS SESで利用する

「メール受信をトリガーにしてなにかする機能」であるAction MailboxはRails6.0からRailsに追加された機能です。なかなか実際に使うことがなかったのですが、最近機会に恵まれてAction Mailboxを導入したので簡単に概要を書き残しておきます。ingress*1にはAWS SESを利用しました。

そもそもAction MailboxはAWS SESを公式サポートしてないんですよ

まず、Action Mailboxが公式にサポートしているingressにAWS SESはありません。Action Mailboxのリリース前にはサポートされる予定があったのですが、AWS SESはSendgridなどの他のメールサービスと比べてAction Mailbox側で考慮すべき点が多く、他のサービスと同一の実装だといろいろ問題があったため最終的に公式サポートがない状態でリリースされました。

その後、有志がAWS SESサポートを入れようと頑張るのですが、Railsコアチームの中にSESを使っている人がいなくてメンテナンスの継続に問題があるということでRejectされます。

しかし最終的にここでの成果物がAWS公式のgemとして採用される、という結果になりました。

aws/aws-actionmailbox-ses-ruby

というわけでAWS SESでAction Mailboxしたい場合はAWS公式である上記gemを使うのが良さそうです。

actionmailbox-ses-rubyを使う時の設定の仕方

actionmailbox-ses-ruby gemのREADMEに設定方法は書かれています。なので単にその通りにやれば良いのですが、僕のようにAWSに詳しくない人間だといくつかハマる可能性があるので個人的なメモとしての設定の流れを箇条書きしておきます。

  • Route53(もしくは他のDNSサーバ)に、メールを受け取りたいSESリージョンに対応したMXレコードを登録する(例: 10 inbound-smtp.us-east-1.amazonaws.com)
  • メール受信用のS3バケットを作成しておく
  • Route53に設定したMXレコードのリージョンで、SESのEmail receiving設定を追加する
    • Recipient conditionsで、Railsに通知したいメールアドレスの条件を設定する
    • Actionsを設定してS3バケットにメールの内容を保存するようにする
      • S3に保存するのはactionmailbox-ses-ruby gem的にはOptionalのようだけど、S3に保存しないと150KBまでのメールしか扱えないようなので実質必須(参考: Publish to Amazon SNS topic action - Amazon Simple Email Service )
      • Action中のSNS topicにSNSトピックを設定する
        • SESではなくS3バケットのプロパティとしてSNSトピックを紐づけることもできるけど、そこからのHTTPSリクエストはaws-actionmailbox-ses-ruby側は考慮していないので注意
  • SNSトピックでは https://example.com/rails/action_mailbox/ses/inbound_emails のようにSubscriptionのEndpointを指定する
    • これを登録するとすぐに正しいEndpointなのか実際にリクエストを投げて確認が行われる
    • actionmailbox-ses-rubyはこの確認をうまく取り扱ってくれるが、うまく取り扱うためにはactionmailbox-ses-rubyを含んだRailsアプリケーションを先にデプロイしておかないといけない
    • さらにSNSのSubscription Endpointが正しいものと確認されていないと、それをSESと紐づけられない模様
    • なのでできる範囲でSESを設定しておき、 actionmailbox-ses-rubyが含まれているRailsアプリケーションをデプロイ→SNSを設定→SESの設定にSNSを追加、という流れになる
  • S3に保存したメールをAction Mailboxから取得する権限設定が必要。actionmailbox-ses-ruby gemのREADME中に記載された設定例ではconfig.action_mailbox.ses.s3_client_options = { region: 'us-east-1' }のようにs3_client_optionsにregionのみ書かれているけどこれはS3を扱えるIAMロールがEC2インスタンスにアタッチされている前提なので、普通にアクセスキーを使いたい場合は次のようにする。
config.action_mailbox.ses.s3_client_options = {
  region: 'us-east-1'
  access_key_id: 'YOUR_ACCESS_KEY_ID',
  secret_access_key: 'YOUR_SECRET_ACCESS_KEY'
}

雑感

上記のポイントを抑えつつ設定すればあとはAction Mailboxのレールに乗るだけです。

AWS SES経由でS3に保存したメールデータをAciton Mailboxで扱う際に、同じデータをActive Storage経由でまたS3にアップロードすることになるのが非効率だなという気もしますがまあこれは仕方がないですね…。

aws-actionmailbox-ses-rubyのスター数は執筆時点で5しかないのでみんなこのgem知らないんじゃないかな、と思い紹介を兼ねて書いてみました。誰かの役に立てば幸いです。

*1:Action Mailboxがメール受信に使う外部サービス

seed-fuをforkした

昨日Findyさんに寄稿した記事が公開されました。もしまだ読んでない方いたら読んで記事下部にある「応援」ボタンをポチッと押してください。Ruby Associationへ応援の数 * 100円寄付されます。

メンテされないgemとどう向き合うか。“普通のOSS開発者” willnetさんの取り組み

この記事内でseed-fuをforkしてseed-doを作ったぞ、という話をしていますが、OSS開発という話の流れの一部で書いているのでスルーしてしまう人もいるかなと思いこのブログ中でも書いておきます。

seed-fuってなに

seed-fuはRailsのシードデータ(本番、開発環境に関わらず)を作るためのgemです。Rails公式としてはdb/seeds.rbがシードデータ用のファイルとして用意されていますが、db/seeds.rbは空のファイルであり、具体的にどうやってデータを用意したら良いのかわかりづらいです。seed-fuを利用するとdb/fixtures/development/*.rbに開発環境でだけ使うデータを用意する、のように一定のレールが敷かれています。このわかりやすさが良かったのか10年くらい前は使っている人が多かったように思います。

が、上記記事中にもあるようにメンテナンスが滞り、いまは作者にも連絡が取れないという状況なのでforkして、既知の不具合を修正したものをseed-doとしてリリースしています。

seed-doが解決した不具合

主な不具合は次の2つです。

後者はなにが不具合なのかよくわからん、という人もいるんじゃないかと思いますが、わざわざforkまでしたのはこれを直したかったからです。ながらRuby会議01でこの問題に関するプロポーザルを出したので通ればそこで詳細発表できるかと思います(プロポーザル通るといいな)。

僕はseed-doを直接は使ってない*1ので新規の機能開発に意欲はない*2のですが、今後も新しいRubyやRailsでちゃんと動くようにするモチベはあるのでもしseed-fuを使っている人がいたら乗り換えをオススメします。

*1:お手伝い先では使っています

*2:もし新機能のアイデアある人いたらPRください

ginza.rb 第90回を開催してWasmについて学んだ

Ginza.rb 第90回 - Wasmについて学ぶぞ - connpass

第90回はWasmについて学びました。

Wasm

y-yagiさんの作ってくれた資料を見ながらワイワイしました。

Wasmはいろんな環境で動くけど、個人的にはやっぱりRubyがブラウザで動くぞというところに魅力を感じますね。

例えば昔はherokuのfreeプランで動いていたOSSのデモがWasmでGitHub Pagesなどでホスティングできるようになると嬉しい。あとは CodePen みたいにコード辺を貼って簡単に共有、実行できる場所があるとバグ報告なども簡単にできてよさそう。

現状全部の機能が使えるわけではないとはいえRailsもブラウザで動くので、今後「PRごとに動作確認する環境を作る」が簡単にできるようになるんじゃないかなと期待しています。

僕個人のWasm利用例としてはメタプログラミングRuby用問題集 kinoppyd/reading-metaprogramming-ruby をブラウザで解けるようにしようと思って試行錯誤しているところです。近日中に公開できるといいな…。

次回

次回は7月4日(金)開催で、Gumroadのソースコードを読んでいきます。

antiwork/gumroad

14年もののリアルワールドRailsアプリケーションのコードから学べることはきっとたくさんあるはず。興味のある方は予定を開けておいてください。