When to use FormObject 【Rails】

Tomoharu Tsutsumi
2 min readMar 21, 2020

There are many design patterns in Rails, and one of them is “FormObject”. If you have studied Rails, you have used or at least heard of this. I think that it is easy to understand the design patterns, but it is difficult to use them properly. That’s why I wrote this article. When should I use “FormObject” ? I’m going to tell you my ideas with my experiences.

What is FormObject?

I think many readers have already known it, but in case that you don’t know it, I wrote the easy introduction.

FormObject is a model, and when your form becomes complex, it is usually used. It includes ActiveModel, so it can be dealt with as ActiveRecord model(ex. validation).

Case:1 you want to solve accepts_nested_attributes_for

When you want to change recored in multiple tables, you usually use accepts_nested_attributes_for. Of course, this method has many merits, but it makes the codes more complex. Some people don’t like it. Instead of it, FormObject can be selected. If you have shoes list web application. There are many shoes on the web page, and the application has 3 tables; shoes, reviews, sizes. When you want to save three objects simultaneously, you have to choose accepts_nested_attributes_for or FormObject. If you selected FormObject, the code would be below.

class PostForm  include ActiveModel::Model  attr_accessor :contents, :real_size  def save(shoe)
shoe.save!
shoe.reviews.create!(contents: contents) unless contents.empty?
shoe.sizes.create!(real_size: real_size)
end
end

and

#controllerdef new
@form = PostForm.new
end
def create
@form = PostForm.new(shoes_params)
end

The code is easy by using FormObject.

Case2: When the validation is so complicated

If your form validations are so complicated and there are a lot of validations, you don’t want to use the class. Maybe you will get disappointed with the codes when you see them next time. How do we wrap this? For example, you are coding CsvImport class, and the class has many validations. You can write codes like below.

class CsvImport
include ActiveModel::Model
attr_accessor :file,
validates :name, presence: true
with_options on: :file do
validate :validationA
validate :validationB
validate :validationC
validate :validationD
validate :validationE
end
def validationA
・・・・・・・・
end
#controllerdef import
@csv_import = CsvImport.new
if @csv_import.valid?(:file)
@csv_import.save!
else
render 'new'
end
end

What if you write this code without wrapping like above and the number of validations are continuously increasing? Your code would be chaos in that case.

Wrap up

In a nutshell, when to use FormObject is like this.

  1. To avoid accepts_nested_attributes_for.
  2. There are many validations

Of course, there are other usages. I’m going to learn it.

If you think this article is good, please follow me!

I inform you of an added article

https://twitter.com/tomoharutsutsum

--

--

Tomoharu Tsutsumi
Tomoharu Tsutsumi

Written by Tomoharu Tsutsumi

5+ years Full Stack SWE (Ruby, Go, TypeScript, JavaScript) | Former Founding Engineer of AI Startup in Canada

No responses yet