今週のお題「小さい春みつけた」
虫が活動し始めた…
今週のお題「小さい春みつけた」
虫が活動し始めた…
勤めている会社にAPIドキュメントがなく、バックエンドはPostmanとかでAPI通信確認してたんだけど、クライアントも容易に確認できた方がいいよねっていうことで、Swagger(OpenAPI)を導入したので、そのお話。(具体的な導入手順は省くよ)
方法としては、主に4つあるかなと考えていて、結果的に4を採用することにした。
1 yamlを直接書く
導入は容易なんだけど、一から手書きするのはしんどいなと言うことで、これは最終手段かなと思っていた。
2 controllerに書く
具体的には、 swagger_blocks
gemとかで、そもそも最終更新が数年前なので、微妙だなぁと思ったのと、既存システムのcontrollerを書き換えるのは、結構大変そうだな。と言うことでやめた。
GitHub - fotinakis/swagger-blocks: Define and serve live-updating Swagger JSON for Ruby apps.
3 RSpecから自動で生成する(
rspec-openapi
)
既存specでも自動でyamlを生成できるやつで、これは運用もしやすそうだなと思ったんだけど、既存specのカバレッジ(どのくらい網羅できてるか)によってドキュメントの質が大きく変わってしまうのと、ちょっと挙動が特殊だったりするので、やめた。
挙動については、↓あたり
RailsでOpenAPI(Swagger)を生成したくてrspec-openapiにPRを立てた話 - スタディスト Tech Blog
でも、結構導入している企業多いなという印象なのでこれでも良さそうとは思ってた。
4 RSpecから自動で生成する(
rswag
)
GitHub - rswag/rswag: Seamlessly adds a Swagger to Rails-based API's
RSpecから自動生成できるという点では3と同じだけど、これは特殊な書き方をしないといけなくて、そのspecのみが生成対象となる。
これは専用の書き方に書き換えたspecのみが生成対象となるため、正しくドキュメント化したいAPIを少しずつ対応することができるので導入しやすいと思った。
ただ、ちょっと書き方に癖があるので、慣れるまでは実装工数がかかりそうだなと思ったんだけど、実際には既にあるspecをコピってきて、ちょっと書き換える。とかでいけるのでそこまでの問題ではなかった。
今後の課題として、レスポンススキーマの生成はどうにかしたいなと思ってる。
components
も便利なんだけど、それすら書くのが面倒だし、実際のスキーマと異なる可能性があるので、実際のAPIレスポンスクラスを基に、rswagのレスポンススキーマが生成できるように変換する処理みたいなのを入れたいと思ってる。
最初から導入することが決まっているなら、2とかもありだと思うけど、後入れなら、3,4かなと思ってる。
正直自分は、Postmanで使っていたのでそこまで恩恵ないかもなんだけど、これで全体の開発スピードが上がったら嬉しいですね!
連続投稿5日目!yoshi!
これを見ながらクソゲーができました。
ひとまず完成
— たにー (@eng_o109) 2024年3月12日
後で色々アレンジしてみよ pic.twitter.com/64FyhA2kpS
たのしいけど、むずい!
初めてC# 触ったけど個人的にはそこまで癖強めとは感じなかった。
クライアントはバックエンドと違って状態管理みたいなのしなきゃ行けないから難しい。
あと、実装時のUnity上で操作するのとスクリプトファイルを書くのとで二つあるので、むずい。なんか新鮮だったけど。
スクリプト作って、アタッチしてーみたいな。
何もしていないのに、なんか新規差分とか出ているのがちょっと気持ち悪い。。(自分だけ?。 gitignoreすべきところしていないとかかも)
ほぼパクリで作ったけど、結構楽しかったので、ブラッシュアップしたり、新しいゲームとかも挑戦してみたいなと思います!
途中死んでるけど、ボスも一応作った
ざっくりジャンルごとにスクショしてみた。
「DIE WITH ZERO」と「限りある時間の使い方」はおすすめ
デンマーク人…はおすすめ
ほかにも読んだ本はあるけど、メルカリとかでかなり売っちゃったから、意外と少なかった。
本は本当に素晴らしいものだと思う。
今後もどんどん読んでいきたい!
のと、お気に入りの本をどんどん増やしていきたい(収集癖)
Railsって長期的な運用は不向きなのかなー
— たにー (@eng_o109) 2024年3月5日
そうなるとGoとか?(技術的負債が起きやすい?)
型書くのめんどう…笑
先日こんなツイートをしたんだけど、型を型を書く事になったとしてどんなメリットがGoにはあるの?とふと疑問に思ったので、調べてみる事に。
プログラミングの実行には、「インタプリタ」と「コンパイル(ラ?)」の2種類があって、インタプリタ(Ruby, Pythonなど)は、コード1行ずつ翻訳→実行をするのに対し、コンパイル(Java, Go)は、全て翻訳してから実行する。という違いがあって、
なので、コンパイル方式のほうが効率がよくて、速いというわけらしい。
そう考えるとRubyってめっちゃ非効率の人みたいじゃん。。
Goは、型指定やシンプルな構文であるため、開発者の癖のあるコードが生まれにくいよう。
これは良さそうだね。そこそこ人数がいるチームとかであれば、なおさら。
正直触ってみないとどこまで統一性があるかわからないけど、確かにRubyは癖が出やすいのかもしれないから、良さそうだね
型を書くからね。
ただ、型を書く手間を考えると個人的には、メリットとしては弱いと思っている。(動的なRubyでもそこまで困ってない)
メリットを考えると、大規模サービス・チーム人数が多い・高速なやりとりを必要とするサービスとかだとGo(コンバイル言語)は向いてそう。
ただ、Ruby(Rails)のサービスを形にする速度はやはりピカイチな気がするので、MVP(必要最低限の機能を備えリリース)して、ユーザの反応見て運用していけそうであれば、Goとかにリプレイス(移行)していく。という流れが良さそう。
後もう一つのメリット忘れてた。
マスコットキャラクターがいるということ
ルビーちゃんとか作って
GoとRubyの言語特性を理解して構築した“いいとこどり“アーキテクチャとは? - Findy Engineer Lab 【RubyとGoの将来性・平均年収・求人数を徹底比較】学ぶべきなのはどっち?|未経験からWebエンジニアへ RUNTEQ BLOG
複雑なクエリを書きたい時、 SQLを直書きできる find_by_sql
メソッドを使うのだが、配列の引数を渡すケースがあったときに、その配列が空だと正常にデータを取得できなくなるよう。
例えば、こんな感じで、1みたいに配列に値があればうまく動作するのだが、2のように空だとうまくいかないっぽい。
# 1. arg_user_ids = [1,2,3] # 2. arg_user_ids = [] query = ( <<~SQL SELECT users.* FROM users INNER JOIN posts ON posts.user_id = users.id WHERE posts.user_id NOT IN (:exclude_post_user_ids) SQL ) User.find_by_sql([query, { exclude_post_user_ids: arg_user_ids }])
だから、微妙なんだけど、分岐させてクエリを変える必要があるみたい?(別案知ってたら教えてほしい)
arg_user_ids = [] if arg_user_ids.blank? query = ( <<~SQL SELECT users.* FROM users INNER JOIN posts ON posts.user_id = users.id -- ここ削除 SQL ) else query = ( <<~SQL SELECT users.* FROM users INNER JOIN posts ON posts.user_id = users.id WHERE posts.user_id NOT IN (:exclude_user_ids) SQL ) end User.find_by_sql([query, { exclude_post_user_ids: arg_user_ids }])
せめて、エラーか警告かほしいところ。。ではある。