Acts as Taggable On Tutorial with Rails 5

acts as taggable on how to rails

For more posts in this series, check out my tutorial on Devise Authentication with Rails 5.

Acts as Taggable On is one of my favorite underrated (and awkwardly named) Rails gems. There’s almost always the need to search or organize objects in a Rails application and using tags simplifies the process so much. It also saves developers new to Rails from writing out monstrous Active Record queries. acts-as-taggable-on is a true work horse, it’s been around since 2010 and has over 8 million downloads to date. Here is a quick getting started guide on using it.

What are tags and why do we use them?

  • Tags help users find related information — they allow you to group one or several instances of a model together without having to create a separate category table.
  • Tags help when users are not sure what they are looking for — for example, think of Amazon and its related products. Sometimes people who buy toothpaste will also buy tooth brushes. But your site will be more powerful if it can tag the items and suggest things like face wash or body cream.
  • Tags allow for a broader ‘category’ label without having to make a standalone table or parent-child-relationship — This means that you can connect several tables without a million foreign keys.
  • Therefore, tags help visitors remain on the site for longer — You want this, because $$$.

Tags essentials

How to use the Acts As Taggable Gem

Install the gem

#add the gem to your gemfile
gem 'acts-as-taggable-on', '~> 6.0' #must be this version for Rails5
#install the gem 
bundle install 
#generate the migrations to create taggings in the db 
rails acts_as_taggable_on_engine:install:migrations
rails db:migrate

Create the model you are going to tag

 

rails g scaffold Restaurant name:string description:string
rails db:migrate
#NOTE: there is no tags column for the restaurants table 
#add this line to app/models/restaurants.rb
acts_as_taggable_on :tags

Use Case 1: I want to add tags to my model in the backend

rails c 
restaurant = Restaurant.new(name: “Lost Heaven”, description: "Yunnan food in the heart of the former french concession", tag_list: “Yunnan”, “Spicy”, “Good Cocktails”) 
restaurant.save
#add or remove tags
restaurant.tag_list.add(“Bund”) 
restaurant.tag_list.remove("Bund")
#return all of the tags of a given restaurant
restaurant.tag_list
#return all of the instances of a class with a specific tag
Restaurant.tagged_with("spicy")

Use Case 2: As a user, I want to be able to tag a model with a specific tag, then search for all the restaurants by their tag

Step 1. Add the tags to permitted params in the controller
#app/controllers/restaurants_controller.rb
def restaurant_params
  params.require(:restaurant).permit(:name, :description, :tag_list)
end
Step 2. Add the tags to the form of the site
#app/views/_form.html.erb
<%= f.input :tag_list %>
Step 3. Search by tag filters
#app/controllers/restaurants_controller.rb
def tagged
  if params[:tag].present?
    @restaurants = Restaurant.tagged_with(params[:tag])
  else
    @restaurants = Restaurant.all
  end
end
#config/routes.rb
get '/tagged', to: "restaurants#tagged", as: :tagged
#app/views/index.html.erb
<% @restaurants.each do |r| %>
  <h2><%= r.name %></h2>
  <p><% r.tag_list.each do |tag| %>
    <%= link_to tag, tagged_path(tag: tag) %>
  <% end %></p>
<% end %>

Use Case 3: As a user, I want to be able to find related restaurants based on their tags

#app/controllers/restaurants_controller.rb
def show
  @restaurant = Restaurant.find(params[:id])
  @related_restaurants = @restaurant.find_related_tags
end
#app/views/restaurants/show.html.erb
<h1><%= @restaurant.name %></h1>
<ul>
  <% @related_restaurants.each do |r| %>
    <li><%= r.name %></li>
  <% end %>
</ul>

Useful Acts_As_Taggable Methods

#returns most and least used tags
ActsAsTaggableOn::Tag.most_used(10)
ActsAsTaggableOn::Tag.least_used(10)
#force all tags to be saved as lowercase
ActsAsTaggableOn.force_lowercase = true
#add tags separated by comma (default), can change to space or others
ActsAsTaggableOn.delimiter = ','

Related Gems

Acts As Favoritor — https://github.com/jonhue/acts_as_favoritor

Acts As Votable (Likable) — https://github.com/ryanto/acts_as_votable

Do you guys find this a useful gem? Are there any other use cases of acts-as-taggable-on that I missed? Let me know below!

You may also like

Leave a Reply