FormObject実装(1回目)
form_objectの実装を進める際に、gem virtus
を使って実装を進めたので、何度かに分けて書いていきます。
環境
gemの導入
Gemfile
に追加します。
# Gemfile ... gem 'virtus' ...
$ bundle install
app/forms
app/forms
のディレクトリを作成します。
mkdir app/forms
config/initialze/forms.rb
を作成して,下記を追加します。
# forms.rb # require_dependecy 'parent_class' Dir.glob('app/forms/**/*.rb') do |f| require_dependency(Rails.roots.join(f)) end
formクラス作成します。
## vim app/forms/offer_form.rb class OfferForm include Virtus.model include ActiveModel::Model attr_accessor :errors attribute :id, Integer attribute :title, String attribute :description, String attribute :main_image, String attribute :side_image_left, String attribute :side_image_right, String attribute :status, Integer, default: 0 attribute :type_of_job_id, Integer attribute :company_id, Integer attribute :adoption_of_shape_id, Integer attribute :confirming, Boolean, default: false attribute :type_of_job_id, Integer attribute job_of_offer, JobOffer validates :title, :status, :type_of_job_id, :adoption_of_shape_id, presence: true def persisted? job_offer.persisted? end ... end
virtus
のREADME
に記載されていて、1:多の関係にある構造も実現できますので、accepts_nested_attributes
を利用せずに
実装をこちらに変更することができます。
余談ですが、Optimistic locking
を実装する上で、accepts_nested_attributesでは、実現できない(仕様が通れば...)ケースがあり
formObjectを通して、lock_version
をコントロールする設計を実現するのに、virtus
を採用(しようとした)経緯がありました。
補足: 誤解を与えそうな表現になっていたので、訂正。virtusは、属性の型、タイプキャスト、初期値を実現します。 virtusを使わずに、form objectを作成することもできます。
今回は、ここまでです。
参考
GitHub - solnic/virtus: Attributes on Steroids for Plain Old Ruby Objects
肥大化したActiveRecordモデルをリファクタリングする7つの方法(翻訳)
Rails4でFormオブジェクトを作る際に気をつける3つのポイント|江の島エンジニアBlog