Using tags creates a better user experience for your clients. Especially If they don't know what they are looking for, It can help them to easily find it. Also, they may stay on your page for longer.
If you are new to Ruby on Rails, creating a join table in your database and understanding many to many relationships can be a bit tricky. When I was working on my recent project instead of creating a join table, I applied taggable gem.
It's always good to remember that If you are using taggable you won't have a tags column in your database. To make it clearer, I am sharing how to use it and how easy it is to implement it in your project.
I built a travel website for my family business and I used the taggable gem to help our clients to find their next destination more easily and to make the Front-end fancier. Let's start implementing it!
Let's start with adding a taggable gem to our gem file.
Gemfile
gem 'acts-as-taggable-on', '~> 6.0'
Do not forget bundle install and generate the migration after adding gem. Next step adding tags to the model you are going to use.
#app/models/tour.rb
class Tour < ApplicationRecord
has_many :bookings, dependent: :destroy
has_many :reviews, :through => :bookings, dependent: :destroy
has_many_attached :photos
acts_as_taggable_on :tags
end
Now we can move to the controller and update it regarding taggable.
#app/controllers/tours_controller.rb
def index
if params[:tag].present?
@tours = Tour.tagged_with(params[:tag])
else
@tours = Tour.all
end
end
and also permit the tag params inside the controller.
private
def tour_params
params.require(:tour).permit(:tag_list, :title, :description, :duration, :group_size, :price, photos: [])
end
Now we can move to the Front-End;
<div class="container">
<h1 id="anchor-tag">Explore Our Top Destinations</h1>
<div class="text-center mb-5">
<% ActsAsTaggableOn::Tag.all.each do |tag| %>
<%= link_to tag, tours_path(tag: tag.name, anchor: "anchor-tag" ), class: "btn-taggable d-inline-block mb-3 #{"active-tag" if params[:tag] == tag.name}" %>
<% end %>
</div>
</div>
Finding related tours based on tags, You should use the find_related_tags method given by the gem on the show page for each tour.
def show
@tours = Tour.all
@tour = Tour.find(params[:id])
@related_tours = @tour.find_related_tags
end
In my project, I created all my tours from seed.rb file. Let's create a tour together.
#db/seed.rb
tour_1 = Tour.create(title: "Cappadocia Hot Air Balloon Ride", description: "Hot Air Balloon Ride", duration: "2 hours", group_size: "10-16 People", price: 189)
tour_1.tag_list = "Cappadocia"
tour_1.save
Basically, that's all! I used taggable gem in both the Tour and Article model. After I created multiple tags for both models, all the tags I created for both models displayed on my tour show page. You can easily avoid using the reject method and you can display only tags you want to show on a certain page. For example; I want to display all the tags except the one that has index number four,
<% ActsAsTaggableOn::Tag.all.reject.with_index { |el, index| index == 4 }.each do |tag| %>
<%= link_to tag, tours_path(tag: tag.name, anchor: "anchor-tag" ), class: "btn-taggable d-inline-block mb-3 #{"active-tag" if params[:tag] == tag.name}" %>
<% end %>
Note -> When the user selects the tag, the page will automatically go up to the top of the page, which is so annoying for the user. To keep the user in the same section, you should give an anchor tag and an id. When users select any of the tags they will stay in the same section.