[Ruby on Rails] Implementation of tagging function/tag filtering function

Introduction

I implemented the tag function in Rails using gem acts-as-taggable-on. The specification is that the user inputs an arbitrary tag on the instance creation screen and saves it in a common pattern. ↓ Implementation image

Like the image ① Create an instance on the new screen

② Confirm the input contents on the confirm screen

③ Redirect to the list screen by executing the create action

④ Click a tag to display a list of instances associated with that tag.

Now let's implement it!

Premise (development environment)

table of contents

1. Preparation 2. Model and Controller 3.View

1. Advance preparation

This time I will use a gem called acts-as-taggable-on, but an error will occur during installation, so let's implement it so that the error does not occur. I will list them in order.

Gemfile


gem 'acts-as-taggable-on', '~> 6.0' #add to

Terminal


% bundle install

Terminal


% rails acts_as_taggable_on_engine:install:migrations

Running rails acts_as_taggable_on_engine: install: migrations will create the required migration files. Normally, rails db: migrate is executed here to reflect it in the database, but if you are using Mysql, an error will occur if you do not do the necessary processing here.

If you migrate it, use rails db: rollback to restore the file.

Execute the command in the terminal as shown in acts-as-taggable-on Official Reference. スクリーンショット 2020-12-23 10.49.07.png

Terminal


% rails acts_as_taggable_on_engine:tag_names:collate_bin

Next, edit the migration file generated earlier. (Be careful with the file name)

php:db/migrate/・ ・ ・ ・_add_missing_unique_indices.acts_as_taggable_on_engine.rb


# This migration comes from acts_as_taggable_on_engine (originally 2)
if ActiveRecord.gem_version >= Gem::Version.new('5.0')
  class AddMissingUniqueIndices < ActiveRecord::Migration[4.2]; end
else
  class AddMissingUniqueIndices < ActiveRecord::Migration; end
end
AddMissingUniqueIndices.class_eval do
  def self.up
    add_index ActsAsTaggableOn.tags_table, :name, unique: true

    # remove_index ActsAsTaggableOn.taggings_table, :tag_id if index_exists? (ActsAsTaggableOn.taggings_table, :tag_id) #Comment out
    if index_exists?(ActsAsTaggableOn.taggings_table, :tag_id) #add to
      remove_foreign_key :taggings, :tags                      #add to
      remove_index ActsAsTaggableOn.taggings_table, :tag_id    #add to
    end
    remove_index ActsAsTaggableOn.taggings_table, name: 'taggings_taggable_context_idx'
    add_index ActsAsTaggableOn.taggings_table,
              [:tag_id, :taggable_id, :taggable_type, :context, :tagger_id, :tagger_type],
              unique: true, name: 'taggings_idx'
  end

  def self.down
    remove_index ActsAsTaggableOn.tags_table, :name

    remove_index ActsAsTaggableOn.taggings_table, name: 'taggings_idx'

    add_index ActsAsTaggableOn.taggings_table, :tag_id unless index_exists?(ActsAsTaggableOn.taggings_table, :tag_id)
    add_index ActsAsTaggableOn.taggings_table, [:taggable_id, :taggable_type, :context], name: 'taggings_taggable_context_idx'
  end
end

① Comment out the 11th line

php:db/migrate/・ ・ ・ ・_add_missing_unique_indices.acts_as_taggable_on_engine.rb


# remove_index ActsAsTaggableOn.taggings_table, :tag_id if index_exists?(ActsAsTaggableOn.taggings_table, :tag_id)

② Add the following description from the 12th line

php:db/migrate/・ ・ ・ ・_add_missing_unique_indices.acts_as_taggable_on_engine.rb


if index_exists?(ActsAsTaggableOn.taggings_table, :tag_id) #add to
  remove_foreign_key :taggings, :tags                      #add to
  remove_index ActsAsTaggableOn.taggings_table, :tag_id    #add to
end

The process is perfect now!

Terminal


% rails db:migrate

Next, put the tag to be displayed on the list screen in seed.rb.

db/seed.rb


#Tagged tying(%w()Described in)
array = %w(Dance Song Shooting Model Salon Cut Model Acting Magic Idling Extra Musical Instrument Performance Remote Possible Tokyo Kanagawa Saitama Chiba Gunma Ibaraki Hyogo Hokkaido Osaka Kyoto Aichi Fukuoka 5000 Yen~10,000 yen~15,000 yen~20000 yen~25,000 yen~30,000 yen~Active recruitment Youtube advertising model)
array.each{ |tag|
  tag_list = ActsAsTaggableOn::Tag.new
  tag_list.name = tag
  tag_list.save
}

Terminal


% rails db:seed

If rails db: seed works, I think mysql will save the data. スクリーンショット 2020-12-23 11.17.07.png

At this point, the preparations are complete.

2. Model and Controller

Add the following description to the model you want to tag.

app/models/event.rb


class Event < ApplicationRecord
    acts_as_taggable  #add to
end

app/controllers/events_controller.rb


class EventsController < ApplicationController

  def index
  #Display tags on the list screen
    @tags1 = ActsAsTaggableOn::Tag.where("id < ?", 10)
    @tags2 = ActsAsTaggableOn::Tag.where(id: 11..22)
    @tags3 = ActsAsTaggableOn::Tag.where(id: 23...29)
    @tags4 = ActsAsTaggableOn::Tag.where(id: 29...31)
  #Display what is out of the tag when searching for a tag
    if params[:tag_name]
      @events = Event.tagged_with("#{params[:tag_name]}").includes(:recruiter)
    else
      @events = Event.all.includes(:recruiter)
    end
  end

  def new
    @event = Event.new
  end
  
  def confirm
    @event = Event.new(event_params)
    if @event.invalid?
      render :new
    end
  end

  def create
    @event = Event.new(event_params)
    @event.recruiter_id = current_user.id
    render :new and return if params[:back] || [email protected]
    if @event.save
      redirect_to root_path
    else
      render :new
    end
  end
  
  def show
    @event = Event.find_by(id: params[:id])
  end
  
  private

  def event_params
    params.require(:event).permit(:event_name, :datetime, :prefecture, :place, :detail, :tag_list)
  #For strong parameters:tag_add list
  end

  def set_user
    @user = current_user
  end

end

The explanation will be summarized later. Let's move on to the View part first.

3.View

Tag your instance

php:views/events.new.html.haml


 = form_with(model: @event, url: confirm_events_path(@event), local: true, id: "new-event") do |f|
     .
     .

   .create-item-2
     = f.label :tag_list, "Tagging"
     = f.text_field :tag_list, value: @event.tag_list.join(','), placeholder: "dance,Tokyo,・ ・ ・"
     .
     .

   .create-btn-field
     = f.submit "To confirmation screen"

php:views/events.new.html.haml


.create-item-2
     = f.label :tag_list, "Tagging"
     = f.text_field :tag_list, value: @event.tag_list.join(','), placeholder: "dance,Tokyo,・ ・ ・"

By nesting the above part in form_with, it means **" I will add a tag to @ event" **.

url: confirm_events_path(@event) However, if the confirmation screen is not sandwiched= form_with(model: @event, local: true, id: "new-event") do |f|It's okay. The controller part also does not require a confirm action. Please see here for the implementation of the confirmation screen (https://qiita.com/anago1030/items/0016bbf99e7fe3b926e1)

@event.tag_list.join(',') By separating them with commas, the data is saved in the form of an array of entered tags.

Display tags on the list screen

php:views/events.html.haml


  %p.tag-word
Search by genre
   - @tags1.each do |genre|
     = link_to "#{genre.name}(#{genre.taggings_count})", events_path(tag_name: genre.name), class: "tag-link"

In the controller part, @ tag1 is defined like this

app/controllers/events_controller.rb


def index
  #Display tags on the list screen
    @tags1 = ActsAsTaggableOn::Tag.where("id < ?", 10)

The meaning is ** "Substitute tags with id less than 10 from the tags created in advance in seed.rb into @ tags1 "**. In view, @ tags1 is listed by each method. The remaining @ tags2`` @ tags3`` @ tags4 is also displayed on the list screen by the same procedure.

(#{genre.taggings_count}) The .taggings_count method will display the number of instances associated with the tag in the view.

events_path(tag_name: genre.name) Click a tag to list the instances to which it is associated.

app/controllers/events_controller.rb


def index
  .
  .
  if params[:tag_name]
    @events = Event.tagged_with("#{params[:tag_name]}").includes(:recruiter)
  else
    @events = Event.all.includes(:recruiter)
  end
end

By setting Event.tagged_with ("# {params [: tag_name]} "), all the information of the instance associated with the tag will be acquired.

That's all for implementation!

in conclusion

Thank you for reading until the end! Thank you for your hard work. ..

References

Rails | acts-as-taggable-Implementation of tag function using on|memorandum Add tag function to Rails. Use acts-as-taggable-on

Recommended Posts

[Ruby on Rails] Implementation of tagging function/tag filtering function
[Ruby on rails] Implementation of like function
Implementation of Ruby on Rails login function (Session)
Ruby on Rails <2021> Implementation of simple login function (form_with)
Implementation of Ruby on Rails login function (devise edition)
[Ruby on Rails] Comment function implementation
[Ruby on Rails] Follow function implementation: Bidirectional
Ruby on Rails Email automatic sending function implementation
[Rails 6] Implementation of search function
[Rails] Implementation of category function
[Rails] Implementation of tutorial function
[Rails] Implementation of like function
[Ruby on Rails] Asynchronous communication of posting function, ajax
Explanation of Ruby on rails for beginners ⑦ ~ Flash implementation ~
[Rails] Implementation of CSV import function
[Rails] Asynchronous implementation of like function
[Ruby on Rails] Introduced paging function
[Rails] Implementation of image preview function
Basic knowledge of Ruby on Rails
[Rails] About implementation of like function
[Rails] Implementation of user withdrawal function
[Rails] Implementation of CSV export function
[Ruby on Rails] CSV output function
[Ruby on Rails] DM, chat function
A note about the seed function of Ruby on Rails
[Rails] Implementation of tagging function using intermediate table (without Gem)
[Ruby on Rails] Introduction of initial data
Let's summarize "MVC" of Ruby on Rails
part of the syntax of ruby ​​on rails
Rails [For beginners] Implementation of comment function
[Rails 6] Implementation of SNS (Twitter) sharing function
[Ruby on Rails] Japanese notation of errors
Explanation of Ruby on rails for beginners ①
[Vue.js] Implementation of menu function Implementation version rails6
[Vue.js] Implementation of menu function Vue.js introduction rails6
[Ruby on Rails] Logical deletion (withdrawal function)
[Rails] Implementation of search function using gem's ransack
Validation settings for Ruby on Rails login function
[Rails 6] Implementation of inquiry function using Action Mailer
[Ruby on Rails] Until the introduction of RSpec
[Rails] Implementation of image enlargement function using lightbox2
Recommendation of Service class in Ruby on Rails
[Rails] Implementation of retweet function in SNS application
Ruby on Rails ~ Basics of MVC and Router ~
[Ruby on Rails] A memorandum of layout templates
Ruby on Rails address automatic input implementation method
[Ruby on Rails] Post editing function (update, delete)
[Ruby on Rails] Individual display of error messages
Implementation of search function
Ruby on Rails Elementary
Ruby on Rails basics
Rails search function implementation
Implementation of pagination function
Ruby On Rails Association
[Rails] Implementation of drag and drop function (with effect)
Docker the development environment of Ruby on Rails project
[Rails] Implementation of multi-layer category function using ancestry "Preparation"
[Rails] Implementation of multi-layer category function using ancestry "seed"
[Ruby on Rails] Post image preview function in refile
[Rails] Implementation of SNS authentication (Twitter, Facebook, Google) function
Explanation of Ruby on rails for beginners ⑥ ~ Creation of validation ~