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!
1. Preparation 2. Model and Controller 3.View
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.
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.
At this point, the preparations are complete.
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
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.
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!
Thank you for reading until the end! Thank you for your hard work. ..
Rails | acts-as-taggable-Implementation of tag function using on|memorandum Add tag function to Rails. Use acts-as-taggable-on
Recommended Posts