Customizing Rails Forms with a Custom FormBuilder

When building forms in Rails, we often need to add custom behavior or default styles to form fields. While Rails provides a flexible FormBuilder through form_for and form_with, there are times when you want to streamline repetitive tasks, such as adding CSS classes to every form input. This is where creating a custom FormBuilder comes in handy.

In this blog post, we’ll explore how to create a CustomFormBuilder that automatically applies a CSS class to form fields, ensuring consistent styling without redundant code. We’ll also see how to implement it using form_for.

Why Use a Custom FormBuilder?

A FormBuilder in Rails helps generate form elements like text fields, password fields, and submit buttons, all tied to a specific model. The default FormBuilder works well, but when your application requires custom logic—like always applying a certain CSS class or adding default options—you can extend it by creating a custom form builder.

This approach keeps your code DRY (Don’t Repeat Yourself) and ensures that all forms follow the same design patterns.

Creating a Custom FormBuilder

Let’s create a simple CustomFormBuilder that adds the Bootstrap class form-control to all text and password fields automatically.

First, create the CustomFormBuilder class in app/helpers/custom_form_builder.rb:

1
2
3
4
5
6
7
8
9
10
11
12
13
class CustomFormBuilder < ActionView::Helpers::FormBuilder
  # Automatically adds the Bootstrap class 'form-control' to text fields
  def text_field(method, options = {})
    options[:class] = "form-control #{options[:class]}"
    super(method, options)
  end

  # Automatically adds the Bootstrap class 'form-control' to password fields
  def password_field(method, options = {})
    options[:class] = "form-control #{options[:class]}"
    super(method, options)
  end
end

In this example, we’ve overridden the text_field and password_field methods. Each method adds the form-control class to the input’s class attribute and then calls super to invoke the original method from the parent class (FormBuilder). This way, our custom logic is layered on top of the default behavior.

Using the CustomFormBuilder in Views

Once the CustomFormBuilder is defined, you can use it in your views with form_for. Here’s an example:

1
2
3
4
5
6
7
8
9
10
= form_for @user, builder: CustomFormBuilder do |f|
  .form-group
    = f.label :username
    = f.text_field :username

  .form-group
    = f.label :password
    = f.password_field :password

  = f.submit "Sign In", class: "btn btn-primary"

In this example:

Why Choose form_for over form_with?

Both form_for and form_with can accept custom form builders. While form_with is the newer syntax introduced in Rails 5.1, some developers still prefer form_for for its explicitness when handling model objects. In this example, we used form_for for simplicity and clarity, but you can easily adapt this to form_with if preferred.

Creating a custom FormBuilder in Rails allows you to encapsulate repetitive form behaviors, such as adding default classes or handling specific input types in a consistent manner. By doing this, you maintain cleaner views, reduce duplication, and ensure that your forms remain consistent across your application.