Serialization and check_box_tag
in Rails 6
There are times when it is useful to simply store an array of arbitrary strings or numbers inside of one column, for example a list of tags for a simple blog application. Here we will see an example of controlling this array with simple check boxes in a Rails form.
Setup
NOTE: This guide assumes you already have Ruby and Rails 6.0 installed.
First create a new Rails project.
rails new serialized-checkboxes
cd serialized-checkboxes/
Create a home page and some scaffolding for a basic Post model.
rails generate controller home welcome
rails generate scaffold Post title:string body:text tags:text
Update the config/routes.rb
to set the root route.
Rails.application.routes.draw do
root 'home#welcome'
resources :posts
end
Create and migrate the database.
rails db:create
rails db:migrate
Serializing and Building the Form
Make the field serialized in app/models/post.rb
.
class Post < ApplicationRecord
serialize :tags
end
Build out the form in app/views/posts/_form.html.erb
.
<% ['development', 'music', 'hiking'].each do |tag| -%>
<%= label_tag "post[tags][#{tag}]", tag %>
<%= check_box_tag "post[tags][#{tag}]", tag, @post.tags&.any?(tag) %>
<% end -%>
We create an array of tags and iterate through them using each
. For each tag we create a label and a checkbox. We name both post[tags][#{tag}]
so that our values will be passed in the correct format to the controller, as well as so that when the label is clicked it will activate the checkbox. Finally we use @post.tags&.any?(tag)
to set the checkboxes as initially checked if those values are already in our serialized store.
Handling the Data
Inside app/controllers/posts_controller.rb
we first add our fields to the parameter allowlist so they will get through from the form. Notice that the tags parameter is set as a hash at the end of the list.
def post_params
params.require(:post).permit(
:title,
:body,
tags: {}
)
end
Create a new private method to format the data of the paramters how we want it, in this case we just want an array of the tag names stored in our serialized column.
def format_tags(parameters)
parameters[:tags] = parameters[:tags].keys
parameters
end
Now update the create
and update
methods to use our formatting method.
def create
@post = Post.new(format_tags(post_params))
respond_to do |format|
if @post.save
format.html { redirect_to @post, notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: @post }
else
format.html { render :new }
format.json { render json: @post.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if @post.update(format_tags(post_params))
format.html { redirect_to @post, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: @post }
else
format.html { render :edit }
format.json { render json: @post.errors, status: :unprocessable_entity }
end
end
end
Finally, run the Rails server and view what we've done.
rails server
open https://localhost:3000
Conclusion
And that's it!
We can now navigate to http://localhost:3000/posts
and create a new post using the checkboxes to store the tags we want for that post.
You can find the code for this tutorial on my GitHub.