[RUBY] [Rails] Implemented hashtag function


I will summarize how to implement the hashtag function.


https://glodia.jp/blog/3936/ https://qiita.com/Naoki1126/items/4ea584a4c149d3ad5472

I implemented it by combining the information from these two articles. Thank you very much.

Complete image

This time, I will explain how to introduce hashtags in photo captions using the photo posting app as a theme. 661b81756d7347895004cbab39aaf1732.png

A hashtag with a link is described in the caption of the photo details screen, and clicking it will display the hashtag page.

Image from Gyazo

Development environment

Implementation flow

--Prepare various models and migration files --Added hashtag save / update action to model --Set routing --Create a helper method --Create a hashtag action on your controller --Edit view

This code

The code is omitted except for the necessary parts.

1. Prepare various models and migration files

Create hashtag model

%rails g model hashtag

Create an intermediate table

%rails g model photo_hashtag_relation

Edit migration file

Set the columns of the table.


class CreateHashtags < ActiveRecord::Migration[6.0]
  def change
    create_table :hashtags do |t|
      t.string :hashname
    add_index :hashtags, :hashname, unique: true


class CreatePhotoHashtagRelations < ActiveRecord::Migration[6.0]
  def change
    create_table :photo_hashtag_relations do |t|
      t.references :photo, index: true, foreign_key: true
      t.references :hashtag, index: true, foreign_key: true

Edit model

Set the validation and association.


class Hashtag < ApplicationRecord
  validates :hashname, presence: true, length: { maximum:99}
  has_many :photo_hashtag_relations
  has_many :photos, through: :photo_hashtag_relations


class PhotoHashtagRelation < ApplicationRecord
  belongs_to :photo
  belongs_to :hashtag
  with_options presence: true do
    validates :photo_id
    validates :hashtag_id

My Great

%rails db:migrate

2. Add hashtag save / update action to model

Add the following code to the photo model. This will save the hashtags in the hashtags table when you post (create) or edit (update) a photo.



  has_many :photo_hashtag_relations
  has_many :hashtags, through: :photo_hashtag_relations
  #Perform just before committing to DB
  after_create do
    photo = Photo.find_by(id: self.id)
    hashtags  = self.caption.scan(/[##][\w\p{Han}Ah-Gae-゚]+/)
    photo.hashtags = []
    hashtags.uniq.map do |hashtag|
      #Hashtag is at the beginning'#'Save after removing
      tag = Hashtag.find_or_create_by(hashname: hashtag.downcase.delete('#'))
      photo.hashtags << tag

  before_update do 
    photo = Photo.find_by(id: self.id)
    hashtags = self.caption.scan(/[##][\w\p{Han}Ah-Gae-゚]+/)
    hashtags.uniq.map do |hashtag|
      tag = Hashtag.find_or_create_by(hashname: hashtag.downcase.delete('#'))
      photo.hashtags << tag


Set up routing

Define a hashtag action in the photos controller and use get to display the page for each hashtag. The URL has the hashtag name at the end. The value in : name will be set later by the helper method.

For example, if the hashtag is #turtle, the URL will be .../photo/hashtag/turtle It will be.


get '/photo/hashtag/:name', to: "photos#hashtag"

Create helper method

Put the following code in photos_helper.rb. If the photos_helper.rb file does not exist, create it yourself.

For helper, see https://www.sejuku.net/blog/28563 etc.

Using this helper method creates a caption with a hashtag with a link. In the code, a URL with the hashtag name at the end is created and set as the link destination when the hashtag is clicked. For the URL before the hashtag name, write the URL you wrote in route.rb earlier.


module PhotosHelper
  def render_with_hashtags(caption)
    caption.gsub(/[##][\w\p{Han}Ah-Gae-゚]+/){|word| link_to word, "/photo/hashtag/#{word.delete("#")}"}.html_safe

Create a hashtag action on your controller

Assign the photo associated with the hashtag to @photos and use it in the hashtag view to display it.


  def hashtag
    @user = current_user
    @tag = Hashtag.find_by(hashname: params[:name])
    @photos = @tag.photos

Edit view

By describing the helper method render_with_hashtags created earlier, the caption with the hashtag with the link will be displayed on the photo details screen.



<%= render_with_hashtags(@photo.caption) %>

On the hashtag screen, the @photos set in the hashtag action is imported and the photos associated with the hashtag are displayed one by one.


<h2>hashtag#<%= @tag.hashname %></h2>
    <% @photos.each do |photo| %>
        <%= link_to photo_path(photo.id) do %>
          <%= image_tag photo.image.variant(gravity: :center, resize:"640x640^", crop:"640x640+0+0"), if photo.image.attached? %>
        <% end %>
    <% end %>

in conclusion

The above is the method of implementing the hashtag function this time. There are a lot of codes that I don't understand, but I hope I can understand them one by one.

** I am a beginner, so if you make a mistake, please point it out m (_ _) m **

Recommended Posts

[Rails] Implemented hashtag function
[Rails] (Supplement) Implemented follow function
Implemented mail sending function with rails
[Rails] Category function
Rails follow function
Implemented comment function
[Rails] Notification function
Implemented follow function in Rails (Ajax communication)
[Rails 6] Asynchronous (Ajax) follow function is implemented
Rails hashtag search implementation
Posting function implemented by asynchronous communication in Rails
[rails] tag ranking function
Rails search function implementation
[Rails, JavaScript] Implemented like function (synchronous / asynchronous communication)
[For Rails beginners] Implemented multiple search function without Gem
Rails application guest login function implemented (devise not used)
Implement application function in Rails
Rails fuzzy search function implementation
[Rails] Implement User search function
Introduced graph function with rails
Search function using [rails] ransack
Implement follow function in Rails
[Rails 6] Implementation of search function
Finally implemented Rails Form object
[Rails] Implementation of category function
Rails ~ Understanding the message function ~
Login function implementation with rails
[Rails] EC site cart function
Ajax bookmark function using Rails
[Rails] Implementation of tutorial function
[Rails] Implement image posting function
[Rails] Implementation of like function
[Rails 6] Pagination function implementation (kaminari)
[Rails] Implemented a pull-down search function for Active Hash data
[Rails] Implementation of CSV import function
[Rails] Asynchronous implementation of like function
Add a search function in Rails.
[Rails] About the Punk List function
Implemented authentication function with Spring Security ③
[Ruby on Rails] Introduced paging function
[Rails] Implementation of image preview function
[Rails] Tag management function (using acts-as-taggable-on)
Implemented hashtag search like Instagram and Twitter in Rails (no gem)
Kaminari --Added pagination function of Rails
[Rails] About implementation of like function
[Rails] Implementation of user withdrawal function
[Rails] Implementation of CSV export function
Create pagination function with Rails Kaminari
Implement simple login function in Rails
Implemented authentication function with Spring Security ①
[Ruby on Rails] CSV output function
[Rails] Voice posting function ~ Cloudinary, CarrierWave
[Rails] Comment function (registration / display / deletion)
[Rails] gem ancestry category function implementation
[Ruby on Rails] Comment function implementation
[Ruby on Rails] DM, chat function
[Rails 6] Like function (synchronous → asynchronous) implementation
Implement CSV download function in Rails
[Rails] Comment function implementation procedure memo
[Rails] Create an evaluation function using raty.js
[Rails] Function restrictions in devise (login / logout)