Ruby on Rails has changed how we build web applications. Early on, the framework came with some great features to help you get started and build robust applications.
However, it can still be tricky to build and handle forms. Simple Form is a great option. Let's examine what Simple Form is, why we might need it, and some real use cases.
Forms and Ruby on Rails
Ruby on Rails really simplifies building applications. Yet, it also requires your constant attention to keep your codebase streamlined and coherent. One strategy is to avoid writing code by using abstractions, for example. Code that isn't in your actual application is code you don't have to manage. That's why we like abstractions so much, right? Simple Form is just such an abstraction that simplifies building forms for web pages.
Forms are generally complex to build, even using Ruby on Rails. Each field requires attention to define the right type and attach it to the correct attribute. Simple Form eases that pain, as you don't need to find the exact type required for each field.
Let's take a form that gets a user's details, with name
, username
, and email
fields. Consider that we have the User
model with similar related attributes. With Simple Form, the form that fills in attributes looks like the following:
Note that we are not specifying the types of each field. Simple Form will pick the correct input type for each field based on the column's type.
This saves us time and keeps the code readable and easier to maintain.
Installing Simple Form
To install Simple Form in your project, add the simple_form
gem to the Gemfile. Once you have run bundle install
, you can use the included generator to set it up correctly for your application.
A note on Bootstrap and Zurb Foundation: Both Bootstrap and Zurb Foundation 5 are supported within Simple Form. So, if you are using one of them, you can use the --bootstrap
or --foundation
parameter with the generator to include additional configurations during the installation. In the case of Bootstrap, this would look like the following:
Basic Usage of Simple Form
As we pointed out earlier, Simple Form will generate a complete form mainly based on the data related to your objects. Yet, it's also important to understand that Simple Form will not only generate the appropriate field for each attribute but also provide labels and display error hints above the input fields themselves!
Let's consider a fresh new Ruby on Rails 7.x application. We'll generate a User model and build a form for it using Simple Form.
Now we can generate a controller with the new
, create
, and index
actions. The aim is to have something we can play with in the form.
These actions require relevant views. Here is a form that handles a user signing up or being added:
In this case, we specify a custom label and error for the username
input. If no such customization is passed, it will do its best to guess what the label needs to be based on the attribute's name.
We have set a custom hint for the password
field and a custom placeholder
for the email
field. Notice, also, the ability to specify an "inline label" instead of one located above the field (the usual default in forms).
It's also possible to disable labels, hints, and errors by passing the false
value for those attributes: <%= f.input :password_confirmation, label: false %>
.
We need to complement this with one more view to make it usable.
You can then start the application using rails s
. Head to localhost:3000/users/new
to see and use the form.
Let's focus on how the form differs from a classic Ruby on Rails form.
A note on validations: Simple Form can work with mandatory fields out of the box. For example, if we were to add the following presence validation in our User model:
This will be used by Simple Form to add a little '*' next to the username
field, specifying that it's mandatory. This doesn't manage the errors automatically, so you still have to handle that in the controller action. Return to the appropriate field that has errors and act on them.
About Column Types and Form Fields
As mentioned earlier, we haven't specified a type for each field. The Simple Form README has a complete list of all available input types and the defaults for each column type. Here are the most used ones:
Column Type | Generated HTML element | Comment |
---|---|---|
string | input[type=text] | |
boolean | input[type=checkbox] | |
(passwords) string | input[type=password] | Any column with a name containing 'password' |
text | input[type=textarea] | |
integer , float | input[type=number] | |
datetime | datetime select | |
time | time select | |
country | select |
Booleans
As we can see in the above table, boolean attributes will be represented, by default, as checkboxes. In many cases, that's what we'll want. But if not, there is a way to customize this in Simple Form with the as
attribute, which allows you to specify if you will show radio buttons or a dropdown instead.
Here is how to specify radio buttons instead:
This will generate the following HTML:
It's impressive that such a small piece of Ruby code gets you such a complete piece of HTML!
HTML
From the previous example, we can see how Simple Form generates a lot of HTML for each field. That includes the HTML for the input field and a wrapper div around the label and input field. We can customize those by specifying a custom class and id using the input_html
and wrapper_html
attributes. Here is an example.
That's also a way to set attributes for the related HTML, such as maxlength
or value
. Let's take the password field from our user form. We can limit the size and length of the field with the maxlength
attribute.
Custom Inputs and Additional Options
Simple Form is a Ruby library that prepares HTML nodes for you. It comes with a whole set of fields, but you can also add your own. To do so, you can create classes inheriting from Simple Form's classes. Let's consider defining a custom social network input field with a little '@' prefix in front of the actual field.
Now we can use it in the following way:
Note that, if your User model doesn't have a
network_handle
attribute, you must add it through a migration or cheat with anattr_accessor
in the model.
i18n Support
As we've mentioned, building forms is often a pain point. But things get even more painful when it comes to websites and applications that support multiple languages. Simple Form, thankfully, follows Ruby on Rails standards. You can use a simple_form
key in the local files to define translations for all labels, hints, placeholders, prompts, etc.
Here is a little example:
Value Objects
Sometimes, we might use custom, non-ActiveRecord classes to instantiate the main object a form relies upon. This can be done to compose data from multiple models into a synthetic one for either business logic reasons or to gather several attributes into a single object.
Whatever the reason, you can still rely on Simple Form to build forms for that kind of object. To do so, the object class needs to implement, in the best case, three methods: to_model
, to_key
, and persisted?
.
The to_model
method will point to the object itself:
The to_key
allows us to point to the identifier attribute for the object — usually, that means an id
attribute named:
Finally, the persisted?
method is there to tell Simple Form if the object is directly persisted or not.
If that method isn't present, the f.submit
helper isn't usable.
There is a faster way, though — including the ActiveModel::Model
module in the class:
And let's use it through the User model.
We can then add a field for the company name within the user form:
Of course, this attribute will not get saved in a table. However, the same concept can be applied to compose a value object with attributes pulled from several models.
Wrapping Up
In this post, we've seen that Simple Form is easy to install and integrate into your Ruby on Rails application. Simple Form not only takes care of the details of each field in your form, but also generates complex and complete HTML so your form can be styled and shaped with ease.
I encourage you to dive into Simple Form's documentation to see how powerful it can be.
Happy coding!
P.S. If you'd like to read Ruby Magic posts as soon as they get off the press, subscribe to our Ruby Magic newsletter and never miss a single post!