ESM アジャイル事業部 開発者ブログ

永和システムマネジメント アジャイル事業部の開発者ブログです。

2019 アジャイル事業部 年度始のご挨拶の会のご案内

f:id:E_Mattsan:20190220140254j:plain

もうすぐ新しい年度が始まります。みなさんどのようにお過ごしでしょうか。

恒例となりましたオブラブカレンダー、今回は4月始まりの2019年度版として完成しました。 各月にはメンバーが推す様々なテーマの内容が凝縮されています。

そしてカレンダーをお渡しする会を今回も開催することといたしました。

会ではカレンダーに書かれたテーマに沿った内容をメンバが LT で語ります。 簡単な軽食とお飲物を用意しておりますので、ご来場いただき LT と食事をひとときお楽しみいただけたらと思います。

そして今回は、平成最後のオブラブイベントでもあります。 オブラブやご自身が推すテーマについて語っていただくための来場者 LT 枠も用意いたしました。

開催は新年度を迎えた4月10日(水)の夜です。

ご参加を希望される方は申し込みページからご登録をお願いいたします。

あとひと月あまりで元号も改まります。

オブラブに縁のある方々も、初めてオブラブカレンダーを目にされる方々も、楽しんでいただける会にしたいと思います。

皆さんのご来場をお待ちしています。

今年も RubyKaigi 2019 に学生を招待します

昨年、仙台で開催された RubyKaigi 2018 にて、弊社としては初めて学生の支援を行いました。 学生支援を検討していた当初は利用してくれる人はいるのかなぁという気持ちがありましたが、 最終的にたくさんの学生からの応募があり、RubyKaigi に参加してみたいという学生は多いということを改めて認識しました。

そこで、福岡で開催される今年の RubyKaigi 2019 でも学生の支援を行います。 今年は、最大 2 名の学生を招待*1したいと考えております。支援を希望する学生は、以下の募集ページにある「キャンセル待ちに登録」から応募してください。

esminc.doorkeeper.jp

今年の RubyKaigi もたいへん内容の濃い RubyKaigi となっています。RubyKaigi は Ruby という技術やコミュニティについて世界で一番濃いイベントだと考えています。自分は初心者だからとか、そういったことで遠慮したりせず、是非応募してください。

このような取り組みを行っていて、かつ、社会人になっても RubyKaigi に参加ができる永和システムマネジメントでは、新卒、中途問わず、一緒に Ruby コミュニティの一員となってアジャイルな開発でお客様へ価値を届けることを目指す仲間を募集しております。

agile.esm.co.jp

*1:弊社の支援では、2020, 2021 に卒業見込みの 20 歳以上学生と制限させていただいておりますが、 Classi 株式会社 さんでは、博士、修士、学部、学年不問(高専生、高校生)のRubyKaigi2019_Classi Scholarship Sponsor という 支援を行われています。すでに応募者多数で抽選となっていますが、併せてご確認ください。

Rails / OSS パッチ会 2019年3月のお知らせ

コミュニティマネージャの koic です。

Rails / OSS パッチ会を 3月13日(水)に開催します。

この会をひとことでいうと、日頃のお仕事で使っている Rails をはじめとする OSS への upstream にパッチを送る会です。

会には RubyRails のコミッターである顧問の a_matsuda もいますので、例えば Rails に送るパッチのネタがあるけれど、パッチを送るに適しているかの判断やパッチを送る流れが悩ましいときなど a_matsuda に相談して足がかりにするなどできます。

以下、前回の活動が関わる成果です。

284km: CSV

github.com

autopp: OpenAPI Generator

github.com

colorbox: Warden

github.com

github.com

kamipo: Rails

github.com

koic: RuboCop

github.com

開催時間は 17:00-19:00 となりますがご都合のあう方はぜひご参加下さい。特に募集ページなど設けませんので、興味のある方は永和システムマネジメントの神田オフィスまでお越し下さい。

agile.esm.co.jp

Rails 6 Beta が出ていたり RailsConf 2019 を翌月に控えていることもあり、その動きに向けた話や終わった後は有志で懇親会などあるかもしれません。

f:id:koic:20190301131315j:plain:w400

Rails / OSS パッチ会 2019年2月のお知らせ

コミュニティマネージャの koic です。

Rails / OSS パッチ会を 2月28日(木)に開催します。

この会をひとことでいうと、日頃のお仕事で使っている Rails をはじめとする OSS への upstream にパッチを送る会です。

会には RubyRails のコミッターである顧問の a_matsuda もいますので、例えば Rails に送るパッチのネタがあるけれど、パッチを送るに適しているかの判断やパッチを送る流れが悩ましいときなど a_matsuda に相談して足がかりにするなどできます。

前回 2019年1月のパッチ会では、Rails 6 に向けた RDBMS ごとの処理系差異の議論など交えつつ盛り上がったりしました。

f:id:koic:20190128134351j:plain:w400

以下、前回の活動が関わる成果です。パッチに向けた設計議論が多めだったため会の時間帯で観測されたパッチは少なめです (私の見落としがいくつかありそう) 。

chiastolite: Rails

github.com

colorbox: Danger

github.com

colorbox: Rails

github.com

kamipo: Rails

github.com

開催時間は 17:00-19:00 となりますがご都合のあう方はぜひご参加下さい。特に募集ページなど設けませんので、興味のある方は永和システムマネジメントの神田オフィスまでお越し下さい。

agile.esm.co.jp

Rails 6 Beta が出ていることもあり、その動きに向けたディスカッションや、終わった後は有志で懇親会などあるかもしれません。

f:id:koic:20190128135143j:plain:w400

GraphQL でファイルをアップロードしたい

こんにちは、hibariya です。さいきん GraphQL でのファイルアップロード方法について知りたいなと思いちょっと検索してみたところ、すぐにはこれといった方法に辿りつけなかったので気になって調べました。手元で試した感じだと GraphQL multipart request specification という仕様が良さそうでしたので、今日はそのことについて紹介したいと思います。

GraphQL でのファイルアップロードはめんどう

現在のところ、GraphQL の仕様ではファイルアップロード方法については特に規定されていないため、自分たちで方法を決めて実装する必要があります。が、これは少し面倒です。HTTP で GraphQL を使う場合、サーバに渡す値はたいてい JSON のようなフォーマットでシリアライズしますが、FileオブジェクトはそのままJSONにはエンコードできません。

{
  "query": "mutation CreateMessage($input: CreateMessageInput!) { ... }",
  "variables": {"input": {"message": "hi", "file": "<アップロードしたい File をここに...??>"}}
}

ですから、GraphQL でファイルをアップロードしようというときには少し工夫が必要になります。方法としてよく挙げられているのは以下の3つでしょうか。

  1. ファイルを Base64 エンコードして JSON に含める
  2. ファイルのアップロードには GraphQL とは別の API を使う
  3. リクエストを multipart/form-data として送る

最初の方法1は、そのままではシリアライズできないファイルを Base64 エンコードすることで JSON として扱えるようにする方法です。クライアントとサーバ間の通信方法を大きく変える必要がなさそうで、シンプルそうに見えます。ただ、巨大なファイルを扱う場合には、あまり考えずにサーバ側のアプリケーションを実装すると巨大な JSON をオンメモリで扱うことになって面倒そうな気がします *1。あとはファイルサイズが若干増えますし、ファイル名のようなメタ情報を自分で渡さないといけないのも少し面倒ですね。

次の2はファイルアップロードを GraphQL API では扱わず、別途用意した REST API などを併用するという方法です。確かに方法のひとつとしては考えられますが、使い方によっては、元々ひとつだったトランザクションを分ける必要が出てくるなど用途を選びそうです。

最後の3は GraphQL のリクエストを multipart/form-data として送る方法です。ここで紹介する GraphQL multipart request specification は、この方法を採用しています。

GraphQL multipart request specification

リクエストに multipart/form-data を使う方法であれば、巨大なファイルは (例えば Ruby なら) Rack のレイヤで少しずつファイルに書き出される *2 ため、サーバサイドのメモリ使用量についての心配はひとまず置いておけます。また、この方法にはいくらか認知されている仕様として、GraphQL multipart request specification というものがあります。

仕様が定めているのは、multipart でどうやって GraphQL リクエストを送るのか、特に GraphQL の変数の値としてとしてどうやってファイルをマッピングするのかというところです。仕様そのものは単純なので、例をまじえて説明します。 README とほぼ同じですが、冒頭の例で説明するとクライアントは以下のような感じの multipart message をサーバに送ることになります。

--------------------------cec8e8123c05ba25
Content-Disposition: form-data; name="operations"

{
  "query": "mutation CreateMessage($input: CreateMessageInput!) { ... }",
  "variables": {"input": {"message": "hi", "file": null}}
}

--------------------------cec8e8123c05ba25
Content-Disposition: form-data; name="map"

{ "0": ["variables.file"] }

--------------------------cec8e8123c05ba25
Content-Disposition: form-data; name="0"; filename="hi.png"
Content-Type: image/png
Content-Transfer-Encoding: base64

(Base64 エンコード済みのファイル)

--------------------------cec8e8123c05ba25--

最初の part を見ると、operations というパラメータの中に GraphQL のクエリや変数が格納されています。ここは相変わらず JSON ですね。ところで肝心の変数 file (variables.input.file) が null となっています。これはtypo ではなくそういうもので、ファイル本体は別の part となっているため、サーバ側で適切にマッピングして、この null を上書きする必要があります。この例では、ファイルは最後の part にある hi.png です。真ん中には map というパラメータの part があります。これは、最初に登場した null と実際のファイルをマッピングするための情報です。この例の { "0": ["variables.file"] } でいうと「0 というパラメータは、variables.file の中身ですよ」といった意味になります。

サーバ側は、この仕様の実装がアプリケーションより下の層にあれば、アプリケーションを大きく変更することなくファイルのアップロードを実現できます。Ruby なら Rack のミドルウェアとして実装して、ファイルを params[:operations][:variables][:input][:file] で参照できるようにする、という具合です。

クライアント側も、変更が必要なのは主にネットワークレイヤになります。実装のひとつに Apollo Link のミドルウェアとしてこの機能を提供しているものがあるので、もし Apollo を使っているならそれを導入することで対応できるでしょう。残念ながら現時点では Relay (Modern) の実装として公開されているものは見当らないのですが、Relay の Network Layer をカスタマイズすることでなんとかなりそうです。Relay の方はちゃんと試してはいないので、知見をお持ちの方がいれば教えてください。

良さと注意点

現時点だと GraphQL でファイルをアップロードする方法としてはこの GraphQL multipart request specification が良さそうだと感じています。理由としては、まず仕様として公開されていて、既にいくつか実装があるということ。また、それらの実装を使うことで既存のアプリケーションの実装を大きく変えなくてもよいというのも良いですね。様々なクライアントに対応できるのが GraphQL の良さのひとつですので、Apollo/Relay どちらからでも使えるというのも重要なポイントだと思います。それから、私はよく Ruby を使うので Ruby の実装があるのも嬉しい。

注意が必要な点としては、あくまで multipart/form-data を前提にしているので、それに対応できないサーバやクライアントでは採用できません。

Ruby でのサーバ側実装

サーバサイドではどんな感じで導入すれば良いのでしょう。最後に GraphQL multipart request specification の Ruby のサーバサイド実装として jetruby/apollo_upload_server-ruby を紹介します。この gem が提供するのは次の2つです。

  • アップロードファイルを表現する Upload というスカラ型
  • GraphQL multipart request specification を実装した Rack middleware

Gemfile に足すと middleware が挿入されるので、基本的にはそれで導入は完了です。ただ、ひとつ注意点があります。このミドルウェアはファイルを ApolloUploadServer::Wrappers::UploadedFile として params に入れてくれるのですが、これは ActionDispatch::Http::UploadedFileDelegateClass でラップしたオブジェクトです。そのため、Active Storage にそのまま渡せないという問題があります (jetruby/apollo_upload_server-ruby#10)。私が手元で検証した際は、workaround として この comment のように IO とファイル名をひとつずつ渡しました。

おわりに

GraphQL でのファイルアップロードについて現状の私の理解を書きました。ここで紹介した GraphQL multipart request specification は、良さそうとは言いつつも、本格的な導入はまだ残念ながらできていません。知見をお持ちの方がいればぜひ教えてください。

もうすぐ大晦日ですね。よいお年を!

参考

Rails / OSS パッチ会 2019年1月のお知らせ

コミュニティマネージャの koic です。

新年最初の Rails / OSS パッチ会を2019年1月24日(木)に開催します。

この会をひとことでいうと、日頃のお仕事で使っている Rails をはじめとする OSS への upstream にパッチを送る会です。

会には RubyRails のコミッターである顧問の a_matsuda もいますので、例えば Rails に送るパッチのネタがあるけれど、パッチを送るに適しているかの判断やパッチを送る流れが悩ましいときなど a_matsuda に相談して足がかりにするなどできます。

前回 2018年12月のパッチ会には、a_matsuda が元 Rails コミッターで来日中の senny を連れてきてくれて、初の海外ゲストを迎えた会になりました。

f:id:koic:20181217150924j:plain:w400

以下、前回の活動が関わる成果です。

amatsuda: ghq_transfer

github.com

kamipo: Rails

github.com

koic: RuboCop

github.com

meganemura: OpenAPI Generator

github.com

sue445: RuboCop

github.com

unasuke: Itamae

github.com

unasuke: Rails

github.com

yahonda: Rails

github.com

開催時間は 17:00-19:00 となりますがご都合のあう方はぜひご参加下さい。特に募集ページなど設けませんので、興味のある方は永和システムマネジメントの神田オフィスまでお越し下さい。

agile.esm.co.jp

Ruby 2.6.0 リリース後の新年最初のパッチ会です。終わった後は有志で新年会などあるかもしれません。