class UserNewForm include ActiveModel::Model attr_accessor :email, :name validates :email, :name, presence: true before_save :email_to_lower_case def save # .. end private def email_to_lower_case # ... end end
class UserNewForm include ActiveModel::Model attr_accessor :email, :name validates :email, :name, presence: true before_save :email_to_lower_case def save # .. end private def email_to_lower_case # ... end end ActiveRecord::Base, ApplicationRecordを 継承してない
class UserController < ApplicationController def create @form = UserNewForm.new(new_params) if @form.save redirect_to new_users_path, notice: 'ユーザを作成しました’ else render :new end end # ... end
2025 17 ③独⾃のライフサイクル処理を持てる class UserNewForm include ActiveModel::Model attr_accessor :email, :name validates :email, :name, presence: true before_save :email_to_lower_case def save # .. end private def email_to_lower_case # ... end end
引⽤︓[Kaigi on Rails 2024] Rails Way, or the highway - Speaker Deck, https://speakerdeck.com/palkan/kaigi-on-rails-2024-rails-way-or-the-highway?slide=76 (2025/09/26閲覧)
使わない実装(=Rails Way) R C T M リクエスト レスポンス 使う実装 • リソース(R) – コントローラ(C) – モデル(M) – テーブル(T)がすべて1対1 • ライフサイクル処理はC(R)UDで⼀様 R C リクエスト F ? レスポンス F’ ? • モデルがFormObjectに置き換わっている • ライフサイクル処理はアクションごとに 変えられる
34 パターン② 2個以上のモデルを操作する 参考︓accepts_nested_attributes_forを使わず、複数の⼦レコードを保存する - Money Forward Developers Blog, https://moneyforward-dev.jp/entry/2018/12/15/formobject/ (2025/09/26閲覧) class CompanyRegistrationForm include ActiveModel::Model attr_accessor :name, :address def save company.assign_attributes(company_params) company.employees << employees company.president = president company.save end end