OpenAPI に対応してる API の client 側を触る機会ができたのでせっかくならということで client の動的生成させてみた。本当はクライアントサイドは Ruby より JavaScript とかの方が充実しているような気がしないでもないけど、一応第一言語なので、悩むことが少なくていいんじゃないかと思って試してみた。
動的生成
notonthehighstreet/svelte: Dynamic Ruby API Client from Swagger JSON Spec
Svelte::Sevice.create(module_name: <NAME>, (url|json): <String>)
と呼ぶと、
Svelte::Sevice::NAME
という Module が生成される。ここ以下の名前空間に OpenAPI の path に応じた module がどんどんできていく。最終的には
Module::Path::To::Resource.operation_id_to_snake_case
みたいなメソッドができあがる。これを call すると、API を叩ける。他の option で大事なのはたぶん
- options
- protocol
- auth
辺り。
とにかく OpenAPI の JSON を読みながら module を掘り、メソッドを call していくことができる。なるほどこれは便利だ。
課題
auth option を create 時に与えるのはよい手ではない。
Svelte は Service Options ( create 時の option ? ) として auth を受け取るが、 例えば token で認証を行う場合には expire 期間を設けることもよくあるのに create 時に与える必要があるため、認証エラーが返ってきたら生成した client を破棄して create し直す処理を client を利用する側に作り込む必要がある。
そして create し直すとそれは Constant の再定義になるので必ず Warning が出てしまう。
ついでに静的生成
- interagent/heroics: Ruby HTTP client for APIs represented with JSON schema
- 試してない
- OpenAPI Generator · Generate clients, servers, and documentation from OpenAPI 2.0/3.x documents
- かなりのコードが生成されるし、手元の環境を思いっきり汚してくるので慎重に使うこと。
使い方はこんな感じ。
npx openapi-generator generate -i path/to/api.json -g ruby
OpenAPI 3 対応
OpenAPI parser と名乗っているものが OpenAPI 3 対応し始めている。
- https://github.com/kevindew/openapi3_parser
- https://github.com/ota42y/openapi_parser
- https://github.com/braintree/open_api_parser
今回は試してません。
9月はとにかく時間がないのは分かっていたので、8月中に施設の予約を済ませて、プログラムを考えてスピーカーにお願いして、あとは meetup #1 の写真をセレクトしていくつか上げたくらいで9月はほとんど準備してません。懇親会やイベント参加登録用の doorkeeper なんかは完全にお任せでした。ありがとうございます。
フタを開けたら meetup #1 と同じくらいの人数になって、ちょっと手狭だなーと思っていたら当日は少し大きな隣の部屋が偶然空いていたので急遽変更して開催しました。
今回は Sinatra を中心に、似たフレームワークが他の言語にも広まっている様子を Perl と node.js で紹介してもらいました。また Bundler のことが分かってないと今後の Ruby を使った開発などはつらいよなぁと思っていたところ、ちょうど興味を持って取り組んでいる様子を Twitter で見てその場で Bundler の話を振ったりしていたんだけど、振った自分もよく分かっていない話がたくさん出てきて面白い感じになったんじゃないでしょうか。ライブコーディングでトークの補強をしてる横でこっちはRailsの話をしていたり、少しずつ発散してきてるのがよい感じ。
本当言うとプログラム考えたり懇親会のネタ考えたりもみんなに参加してほしいんだけど、まだちょっとそこまでの空気にはなっていないので、次回は
No Progam
でいこうと思います。どう使うかは自分(たち)次第です!
個人的には9月の仕事の打ち上げ的な意味合いが大きくなったおかげでだいぶ飲みすぎてしまいました。反省。次回はほどよくいこう。
今まで手作業でカレントディレクトリにしかリンクを置こうとしたことがなかったので悩んだことがなかった。
相対パスでリンクを置こうとする場合のパスの基準は、カレントディレクトリはなくリンクを置く場所なのであった。
super
+ parent <- cwd
+ child
<- link
+ parent2 <- 実体
みたいなツリーになっているとき、cwd で
ln -s ../parent2 child/parent2
みたいにやっちゃいがちだけど、実際には
ln -s ../../parent2 child/parent2
にしないといけないのね。
面倒なら絶対パスにしとけと。
以下、使ったのは ruby 1.8.4 (2005-12-24) [powerpc-darwin]
ruby -e 'require "test/unit"
require "pp"
pp Test::Unit::Assertions.instance_methods.grep( /assert/ ).sort'
結果。
["assert",
"assert_block",
"assert_equal",
"assert_in_delta",
"assert_instance_of",
"assert_kind_of",
"assert_match",
"assert_nil",
"assert_no_match",
"assert_not_equal",
"assert_not_nil",
"assert_not_same",
"assert_nothing_raised",
"assert_nothing_thrown",
"assert_operator",
"assert_raise",
"assert_raises",
"assert_respond_to",
"assert_same",
"assert_send",
"assert_throws"]
pp がスキ。
pretty だから。
※ 実際には irb 上で叩いてますが、そこは適当に補完するなり。
Rubyist Magazine - Rubyist Hotlinks 【第 16 回】 essa さん
何が面白いって高橋さんの話が面白い。
……。
それでいいのか?
いろいろ刺激になったんだけど、書いてみたら引用ばっかりになったので公開しないことにした。今回も勉強になりました(ぺこり)
などと他人事モードでひどいことを書いてみる。