30
37

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Railsで作ったインスタもどきのキャプションにハッシュタグを実装

Last updated at Posted at 2018-06-11

#概要
Rails5でインスタもどきを作ってみたものの肝心の検索とハッシュタグが無いという未完成なものとなっていた。始業前の空き時間を使ってハッシュタグの実装をしたのでコードを貼ってみる。

#既存(Tutorial)に加えて準備する必要があるもの
・hashtag用のテーブル
・hashtagとmicropostの中間テーブル

#完成した姿
完成.png
完成2.png
・#記号を判断して次のスペースまでの文字列をハッシュタグとして抽出しDBに保存
・ハイパーリンク化されており、クリックするとハッシュタグのページになる

#テーブル準備
##ハッシュタグモデルの作成

$ rails g model Hashtag hashname:string

##マイグレーションファイル編集

/db/migrate/...create_hashtags.rb
class CreateHashtags < ActiveRecord::Migration[5.2]
  def change
    create_table :hashtags do |t|
      t.string :hashname
      t.timestamps
    end
    add_index :hashtags, :hashname, unique: true
  end
end

##中間テーブルの作成

$rails g migration CreateMicropostHashtags micropost_id:references hashtag_id:references

##マイグレーションファイル編集

/db/migrate/...create_micropost_hashtags.rb
class CreateMicropostHashtags < ActiveRecord::Migration[5.2]
  def change
    create_table :hashtags_microposts, id: false  do |t|
      t.references :micropost_id, index: true, foreign_key: true
      t.references :hashtag_id, index: true, foreign_key: true
    end
  end
end

##マイグレーション

$rails db:migrate

#モデルの編集
##マイクロポストモデルに下記を追加

/app/models/micropost.rb
  has_and_belongs_to_many :hashtags

  .
  .
  .

  #DBへのコミット直前に実施する
  after_create do
    micropost = Micropost.find_by(id: self.id)
    hashtags  = self.content.scan(/[##][\w\p{Han}ぁ-ヶヲ-゚ー]+/)
    hashtags.uniq.map do |hashtag|
      #ハッシュタグは先頭の'#'を外した上で保存
      tag = Hashtag.find_or_create_by(hashname: hashtag.downcase.delete('#'))
      micropost.hashtags << tag
    end
  end
 
  before_update do 
    micropost = Micropost.find_by(id: self.id)
    micropost.hashtags.clear
    hashtags = self.content.scan(/[##][\w\p{Han}ぁ-ヶヲ-゚ー]+/)
    hashtags.uniq.map do |hashtag|
      tag = Hashtag.find_or_create_by(hashname: hashtag.downcase.delete('#'))
      micropost.hashtags << tag
    end
  end

##中間テーブルモデル

/app/models/hashtag_micropost.rb
class MicropostHashtag < ApplicationRecord
  belongs_to :micropost
  belongs_to :Hashtag
  validates  :micropost_id, presence: true
  validates  :Hashtag_id,   presence: true
end

##ハッシュタグモデル

/app/models/hashtag.rb
class Hashtag < ApplicationRecord
  validates :hashname, presence: true, length: {maximum:99}
  has_and_belongs_to_many :microposts
end

#マイクロポストコントローラーにハッシュタグのアクションを追加

/app/controllers/microposts_controller.rb
  def hashtag
    @user = current_user
    @tag = Hashtag.find_by(hashname: params[:name])
    @microposts = @tag.microposts.build
    @micropost  = @tag.microposts.page(params[:page])
    @comment    = Comment.new
    @comments   = @microposts.comments
  end

ここは少しビューの仕様が違うので人によっては不要になる宣言があるかもしれません

#マイクロポストヘルパーの編集

/app/helpers/microposts_helper.rb
module MicropostsHelper
  def render_with_hashtags(content)
    content.gsub(/[##][\w\p{Han}ぁ-ヶヲ-゚ー]+/){|word| link_to word, "/post/hashtag/#{word.delete("#")}"}.html_safe
  end 
end

せっかく全角にも対応しようとしたものの、deleteメソッドで複数文字を指定するやり方が分からず断念。。。

#ルーティング

/config/routes.rb
get '/post/hashtag/:name', to: "microposts#hashtag"

#ビュー
##キャプション(ハッシュタグがユーザーによって書かれるところ)

/app/views/microposts/_micropost.html.erb
<%= render_with_hashtags(micropost.content) %>

##ページ遷移後のハッシュタグページ

/app/views/microposts/hashtag.html.erb
<% provide(:title, @tag.hashname) %>
<div class="row">
  <div class="col-md-9">
    <div class="block1_hash">
       <%= image_tag("hashtag.png") %>
         <div class="block2_hash">
            <div class="name_hash">
               <%= @tag.hashname %>
            </div>
         <div class="edit_hash">
            <%= render 'users/follow_form' %>
         </div>
        <div class="fllw_hash">
          <%= render 'shared/user_info_default' %>
          <span style="margin-right:15px;"></span>
          <%= render 'shared/stats_default' %>
        </div>
       </div>
     </div>
  </div>
</div>
 
 <div class="row">
   <div class="posted_content">
     <div class="col-md-8">
       <div class="picture_hash">
         <%= render @micropost %>
       </div><!-- .picture -->
     </div>
   </div>
</div>

基本的にはユーザーページと同じデザインです。

#参考VTR
Ruby on Rails - adding hashtags

今月の社内プレゼンのネタができてよかったです。。。
この調子でがんばります。
編集箇所やアドバイス等ありましたらお気軽にお声がけくださいm(_ _)m

30
37
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
30
37

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?