Rails form helpers have been around for so long that they seem unquestionable, but did you know there’s a way to build forms in Rails that are easier to customize and permit their own strong parameters?
Superform is a new form helper library built from scratch on top of Phlex that makes building forms in Rails less tedious. Here’s what a Superform looks like:
# ./app/views/posts/form.rb
class Posts::Form < ApplicationForm
def template(&)
labeled field(:title).input
labeled field(:body).textarea
end
# This would actually be in the ApplicationForm
# superclass. It's added here for clarity.
def labeled(component)
div "p-4" do
render component.field.label
render component
end
end
end
It can then be rendered in Erb, HAML, or any other templating library. Like any view component: create an instance, pass it the @post
, and you’ll see a form.
<h1>New post</h1>
<%= render Posts::Form.new @post %>
But the real superpower comes from creating an instance of the form in the controller so it can permit its own parameters.
class PostsController < ApplicationController
include Superform::Rails::StrongParameters
def create
@form = Posts::Form.new(Post.new)
@post = assign params.require(:post), to: @form
if @post.save
# Success path
else
# Error path
end
end
end
Never again will you wonder, “why is my form not updating?” in your Rails development environment only to realize you forgot to add a strong parameter to Rails. 🤦♂️
How does Superform permit parameters?
Unlike Rails form helpers, Superform keeps tracks of the field names when the field()
method is called in the view where you build the form. For example, in this form below the :title
and :body
attributes are passed into the field
method, which adds them to an internal list of permitted parameters.
# ./app/views/posts/form.rb
class Posts::Form < ApplicationForm
def template(&)
labeled field(:title).input
labeled field(:body).textarea
end
end
Superform doesn’t actually use Rails strong parameters though—instead the assign
method recursively goes through each field
defined in the Superform and assigns the corresponding parameter to that field. If the field is not defined, its not assigned.
assign params.require(:post), to: @form
It’s not really magic, it’s just a form builder that’s both aware of its own structure and visual appearance. Contrast with Rails built-in form builders, which is only capable of describing visual its appearance without knowledge of the fields it’s permitting.
Install Superform in your Rails app
If you’re read to get your hands dirty with Superform, add it to your Rails app.
$ bundle add superform
$ rails g superform:install
This installs Phlex and Superform in your Rails app. You’ll also see the ./app/views/application_form.rb
file in your Rails project that will look familiar to the forms above. Read the Superform docs to see how the form helpers work and have a look at the Phlex website to get a feel for the basics of how you’d build your own HTML components using Ruby.
Customize the look and feel of forms
Since Superform is built on top of Phlex, inputs can be extended to emit the HTML markup your application needs from the ApplicationForm
class. Here’s an example where we create a MyInputComponent
class that includes inline error messages.
# ./app/views/forms/application_form.rb
class ApplicationForm < Superform::Rails::Form
class MyInputComponent < ApplicationComponent
def template(&)
div class: "form-field" do
input(**attributes)
if field.errors?
p(class: "form-field-error") { field.errors.to_sentence }
end
end
end
end
class Field < Field
def input(**attributes)
MyInputComponent.new(self, attributes: attributes)
end
end
end
Additionally, methods can be added to the ApplicationForm
class that makes common form tasks a bit easier.
class ApplicationForm
def labeled(component)
div class: "p-4" do
render component.field.label
render component
end
end
def submit(text)
button(type: :submit) { text }
end
end
These methods can be called from form sub-classes and HTML will be emitted.
Wrap up
Superform is a great way to create highly re-usable and customizable forms that permit their own parameters in Rails.
Superform permits its own parameters - Makes building forms much faster since you don’t have to worry about adding the parameter to the controller while building a form.
Forms can be customized with Phlex components - Superform is built from the ground-up with Phlex components. This makes it easier to mix regular HTML into the helper.
Superform is still a work in progress. It hasn’t reached 1.0 yet and features like select > options
are still being developed, but already its being used for sophisticated form use cases, like batch selection UI in a demo app.