今日で現職在籍ちょうど一周年🥳
オファー承諾から一年経った🎞️
— Ryuta Kamizono (@kamipo) 2026年8月3日
(入社日は8月10日) pic.twitter.com/aBF6mLo67L
この一年ぐらいの出来事をいくつか振り返ってみようと思って書き始めたら、仕事パートだけでだいぶ量いったからタイトルを「仕事の近況2026」にした。その他の近況については気が向いたらそのうち書く。
あと、2026年9月19日(土)に名古屋Ruby会議05でなんか話すのでよかったら聴きに来てね👂 昔書いたコードの話してもアレなんでたぶん最近Railsコミッターとして書いたコードについてなんか話すと思います🙂↕️
仕事
- Rails 7.0から最新Rails対応企業に
- 仕事で遭遇した問題の修正をupstreamに
基本的にRailsアプリケーションのPRは全部巡回してて気になるとこあったらコメントしてるので、その際に「ここ排他制約使うといいんやけどなぁ〜〜」と思うことが度々あった。
たとえば入社当初、何らかの機能(契約)の有効期間を管理してるテーブルにはenabled_on, disabled_onというカラムがあって、DBの制約上は各機能毎のenabled_onにユニーク制約を張って開始日の衝突はDB制約で排除して、期間がオーバーラップしてるかどうかのバリデーションはアプリケーション側で独自にやっていた。
それな〜〜、ポスグレではEXCLUDE USING gist (function_id WITH =, daterange(enabled_on, disabled_on, '[]') WITH &&)するとオーバーラップまでDB制約でチェックできるんやけどなぁ〜〜、と思ってコメントしようとすると、なんとRails 7.0(その時点ですでに4ヶ月前にEOL)のDSLでは排他制約をサポートしていない、サポートしてないRailsだとridgepoleから見たときに制約backedなインデックスが漏出してdiffがおかしくなるので使えない…!ということが3回ぐらいあってダルすぎたので、Railsバージョンアップなんぞに必要なのは気合いだけなんでブロッカーを速攻全部つぶしてRails 7.1に上げた😤
これで使えるかと思ったら、ユニーク制約と違って排他制約違反を個別にキャッチできるようになっていなかった。なのでエラークラスも足した(今まで誰も使ってなかったんか?)
Rails 7.0やと使えん機能のひとつが排他制約やったんやけど、実際使おうとしたら排他制約違反のハンドルできんことが発覚したので例外クラス追加しときました⛓️https://t.co/3G70xIBXBV https://t.co/1VeSZPn3Kz
— Ryuta Kamizono (@kamipo) 2025年9月1日
あとマニアックなのでいうと、外部APIリソースのデータへの操作ログを保存するPRを通りがかりに見つけた際に、あるリソースはsid="CAabcxyz..."みたいな文字列になってて別のリソースはconversation_id="CON-abcxyz..."みたいになってて、それらの値を同じカラムにぶち込む設計になっていた。
そらまぁデータを肉眼で眺めたりresource_id LIKE 'CA%'みたいなクエリでフィルタリングすれば選り分けられなくもないが、さすがにここはRailsなのでpolymorphic関連にしてそれぞれの外部リソースIDがどのリソースタイプなのか分かるようにしたいやろ。
ということでサクッと修正したろ思ったら、なんとRails 8.1ではpolymorphic belongs_toの外部リソースのIDはプライマリーキーであるかもしくは全部のリソースで指定した同名のカラムでないと動かないようになっていた。なんとかalias_attributeで同名に見せかけて回避しようとしたがRailsのassociationはまさかのalias_attribute未対応…
さすがにちゃんと動いてほしいんでこれも直しときましたわ。
- Support polymorphic associations with custom primary keys through `:inverse_of` by kamipo · Pull Request #57795 · rails/rails · GitHub
- Restore `alias_attribute` support in associations by kamipo · Pull Request #58348 · rails/rails · GitHub
あとRails + PostgreSQLで開発するのはじめてだったから、annotaterbがユニーク制約とか排他制約とか遅延制約の表示サポートしてないなとかridgepole環境下でVALIDATE CONSTRAINTするの面倒すぎるとかいう問題にもはじめて遭遇してそういうのも直してた。
- Annotate PostgreSQL unique and exclusion constraints by kamipo · Pull Request #364 · drwl/annotaterb · GitHub
- Show DEFERRABLE INITIALLY on foreign keys by kamipo · Pull Request #365 · drwl/annotaterb · GitHub
- Ignore `validate: false` diff when existing constraint lacks `:validate` by kamipo · Pull Request #716 · ridgepole/ridgepole · GitHub
- Emit `validate_constraint` when DB is NOT VALID and DSL implies validated by kamipo · Pull Request #718 · ridgepole/ridgepole · GitHub
レイルズチョットデキルのが仕事に役立ってよかった🥰
外にコードが出せるやつじゃない成果だと、ルール分岐設定の複雑さが人間の認知の限界を超えてこの世の終わりすぎたので、超絶簡潔な構造にするリファクタリングをしてた。
分岐アクションや設定が五月雨式に建て増しされてきた結果、同じ構造のテーブルが何個もあったり設定テーブルとの中間テーブルが組み合わせ爆発してたりしたのを、ひたすら二重書き込み->データ遡及->参照切り替えを繰り返して中間テーブル約30個を亡き者にして各設定テーブルを各分岐アクションテーブルとのpolymorphic関連にした。
コード側も各ルール分岐設定コントローラーが、作られた時期も実装者も違うが故にそれぞれがまったく異なる音楽性で実装されてたので、なんか実装を追加しようとすると音楽性の違う各コントローラーに実装を追加する必要があり、実装漏れや修正漏れが度々起きていた。
それを、ひたすらコードをソリティアしまくって徐々に何が共通処理で何が個別の処理なのか整理して抽出していった結果大統一ビルダークラスが爆誕し、コントローラーはビルダーを呼び出すだけになった。なんやかんやここまでやるのに半年かかったけど、以前は対照的な実装をしたいだけやのにやたら面倒でバグったりしてたのを、今は逆に非対称な実装をそう簡単にはできないような構造になったので実装漏れやバグは起こすのが難しくなったと思う。
大満足🥰