I'm working on an application that requires me to fill a model through several pages.
Hence, I need to validate each portion of attributes presented in each form.
I've found a way to do so, but I'm wondering if this seems correct, and if I could improve my code ?
def general
@user = User.new
end
def save_general
session[:user] ||= {}
@user = User.new(params[:user].permit(:first_name))
#Apparently, I need to run this once, to populate the errors array.
@user.valid?
unless @user.errors[:first_name].empty?
render :general, status: :unprocessable_entity
else
session[:user][:first_name] = params[:user][:first_name]
end
end
You can easily move parts of the buisness logic out of the model into separate classes:
class UserNameForm
include ActiveModel::Model
include ActiveModel::Attributes
attribute :first_name, :string
validates :first_name, presence: true
# This will make it behave like a User in forms.
def model_name
User.model_name
end
end
This is commonly referred to as the form object pattern.
def save_general
@form = UserNameForm.new(params[:user].permit(:first_name))
# NEVER unless and else together
if @form.valid?
session[:user] ||= {}
session[:user].merge(form.attributes)
else
render :general, status: :unprocessable_entity
end
end
It's kind of questionable if you want to tuck the attributes away into the session like this. On a successful form submission you could just render the next step of the form and include the stuff that's already been filled in as hidden inputs.