Otemachi.rb#20でLTしてきた
概要
Otemachi.rb#20で「突撃!隣のフォームオブジェクト」という話でLTしてきました。
タイトルは某番組をインスパイアしたものの、内容はこちらのフォームオブジェクトに関する取り組みについてなので、完全にタイトル詐欺である。
スライド
内容について
責務がごっちゃでどこに何書いてるかわけわからんカオスなプロダクトを、制度変更に際して色々と整理している。
その中でフォームオブジェクトを採用しており、それをActiveTypeというgemで対応した。
ActiveTypeについて
めちゃくちゃざっくり言うと非ARモデルをARオブジェクトっぽく扱えるようにして、かつARオブジェクトもいい感じに継承できるっていうgem。
class HogeForm < ActiveType::Object attribute :name, :string attribute :email, :string validates :name, :email, presence: true end
みたいなのがかけたり
class User < ApplicationRecord has_one :address, dependent: :destroy end
みたいなARオブジェクトを
class FugaForm < ActiveType::Record[User] change_association :address, class_name: 'AddressForm' accepts_nested_attributes_for :address end
みたいに完全に置き換えれたりする。
スライドに入れれなかったけどcreateとかupdateとかのコンテキストに応じて処理が違うのであれば、共通の処理はxxxForm::Baseに書いて、それを継承してxxxForm::Createとか、xxxForm::Updateみたいなこともできたりする。
(くっそ雑なので継承に関しては用法用量を正しく守ってお使いください)
class UserForm::Base < ActiveType::Record[User] # 関連付けとか共通な処理 end class UserForm::Create < UserForm::Base # create用の処理 end class UserForm::Update < UserForm::Base # update用の処理 end
ちなみにupdate等の処理に際してActiveTypeオブジェクトに変換する際には
user = User.find(params[:id]) @user_form = ActiveType.cast(user, UserForm)
といった感じでActiveType.castメソッドを用いると変換できる。
懇親会
懇親会で話があったのが、ARオブジェクトのバリデーションをFormオブジェクトに完全に移譲するとバッチ処理とか大丈夫なのか、と言う話があった。
これはたしかにけっこう悩みどころで、直接ARオブジェクトを操作することをいかに禁止するかというのはなかなか難しい部分だなと思う。
仮にバリデーション忘れてもpresence: true程度であれば、db上でnull: falseをきっちりかけてればこと足りるけど、複雑なバリデーションは対応難しいっていうのは間違いない。
ただ、バッチ処理に関してはActiveType.castの一手間がかかるけど、その1行の手間で責務のカオスさが減るならいいのかな、とは思ってます。 (エンジニアが一人だからOKな話で、ほかに強い人いたら即NGくらうかも)
この辺の各オブジェクトの責務と言う部分に関しては相談する相手等がいなくて真剣に分からないので、だれか教えていただきたいところです。
LTを終えて
だいぶ詰め込みすぎて、早口で喋らざるを得なくなってしまった。
喉のコンディションが悪かったのもあって、聴きづらかったであろうことは申し訳なかったなと。
あと、castの部分とかも話せてなかったので、だいぶ分かりにくくなってしまった気がする。
5分だからこそ伝える内容うまく絞らないとなー。
でも、やっぱり前で話すの楽しいよね。
やるまでは「なんでLT枠でエントリーしちゃったかなー」とか思うんだけども。
不思議なものである。