class MemberProfileForm
include ActiveModel::Model
attr_accessor :member, :headline, :profile, :time_zone
validates :headline, length: { maximum: 80 }
validates :time_zone, inclusion: { in: ActiveSupport::TimeZone.all.map(&:name) }
def save
return false unless valid?
member.update!(headline: headline, profile: profile, time_zone: time_zone)
end
end
class SettingsController < ApplicationController
def update
form = MemberProfileForm.new(member: current_member, **settings_params.to_h.symbolize_keys)
if form.save
redirect_to settings_path, notice: 'Updated.'
else
render :edit, status: :unprocessable_entity
end
end
private
def settings_params
params.require(:member).permit(:headline, :profile, :time_zone)
end
end
When controllers become parameter jungles, use a form object. It centralizes coercion, validations, and save logic. This pattern is extremely effective for admin panels and multi-step flows.