Mateus Nava

Mateus Nava

January 10, 2022

Autocomplete with Rails 7 (Hotwired turbo)

By Vardan Papikyan (unsplash.com)
By Vardan Papikyan (unsplash.com)
I watched the great video https://www.youtube.com/watch?v=PfCU0Nni8fI and after that, I tried to create a simpler auto-complete, without explicit turbo-stream.

The project consists of having a text field, when the user fills in and submits, the screen will show the filtered results.

The first step is: Creating a New Project (Is just a command, not too long of blablablablabla…)
rails new autocomplete # I'm Using rails 7.0.1 and Ruby 3.1

Now let's create a scaffold for the cities:
rails g scaffold city name:string

At this point, we have a 100% working CRUD but is very ugly, you can use https://simplecss.org/ to magically beautify your CRUD.

CRUD with simplecss


Creating a seed to generate cities, we will use the Faker gem.
# db/seeds.rb
1_000.times do
  City.create!(name: Faker::Address.unique.city)
end

And run:
rails db:seed

Change the index method of cities_controller to search the cities based on the q parameter:
def index
  @cities = City.where('name Like ?', "%#{params[:q]}%")
end

And change the cities/index.html.erb to this:
<p style="color: green"><%= notice %></p>

<h1>Cities</h1>

# data-turbo-frame: indicates that when the form is submitted only the cities in the frame will be updated
<%= form_with url: cities_path, method: :get, data: {'turbo-frame': 'cities'} do |form| %>
  <% form.search_field :q, autofocus: true %>
<% end %>

# Put the list in the frame cities
<%= turbo_frame_tag :cities do %>
  <div id="search-result">
    <%= pluralize(@cities.count, 'city') %> found
  </div>

  <div id="cities-container">
    <% @cities.each do |city| %>
      <%= render city %>
      <p>
        <%= link_to "Show this city", city %>
      </p>
    <% end %>
  </div>
<% end %>

<%= link_to "New city", new_city_path %>

_city.html.erb
<p>
  <strong>Name:</strong>
  <%= highlight(city.name, params[:q]) %>
</p>

When the form is submitted, only the frame of cities will be updated, this is possible by the https://turbo.hotwired.dev/handbook/frames.

There is some overhead because there is all the HTML in the response and not just the frame, but I think it's a reasonable price to pay due to the simplicity of the solution.

Network Tab