12
10

More than 3 years have passed since last update.

○witterもどきのアプリでハッシュタグ機能を実装してみた。

Last updated at Posted at 2019-12-19

はじめに

どうも、Pirikaraです。
今回は適当に作った○witterもどきのアプリで、ハッシュタグ機能を実装してみたので共有したいと思います。

まずはrails new

まずはT○itterもどきのアプリを作ります。
tag機能を実装するので、rails newでtag_appを作ります(適当)

tweetモデルとtagモデルを作成しますが、
両者は多対多の関係なので、中間テーブルとしてtweet_tagモデルも作っておきます。

tweet.rb
class Tweet < ApplicationRecord
  has_many :tweet_tags
  has_many :tags, through: :tweet_tags
  #写真の投稿も可能にするために、carrierwaveとminimagickを入れておいた
  mount_uploader :image, ImageUploader
end
tag.rb
class Tag < ApplicationRecord
  has_many :tweet_tags
  has_many :tweets, through: :tweet_tags
end
tweet_tag.rb
class TweetTag < ApplicationRecord
  belongs_to :tweet
  belongs_to :tag
end

まずはImageとTextのみ投稿ができるTw○tterもどきアプリを作りました。

Image from Gyazo
コードはこちら。

tweets_controller.rb
class TweetsController < ApplicationController
  def index
    @tweets = Tweet.all
  end

  def new
    @tweet = Tweet.new
  end

  def create
    tweet = Tweet.create(tweet_params)
    redirect_to tweets_path
  end

  private

  def tweet_params
    params.require(:tweet).permit(:image, :text, :tag_ids)
  end
end

現在『Tags』のプルダウンには何も入っていませんが、Tagsテーブルに登録されているものが表示される仕様です。
今回はtextarea内に『#(ハッシュタグ)』があれば、それ以下をtagとして認識、Tagsテーブルに保存される形でコードを書いていきたいと思います。

仕様と進め方の確認

  1. textareaに『#(ハッシュタグ)』があれば『#』以下をtagとして認識し、Tagsテーブルに保存する
  2. 一覧表示画面にて、tag名が『#○○○』の形で表示される
  3. 新規投稿画面にて、Tagsのプルダウンにこれまで登録されたTagが表示される。

今回はtweets_controllerのcreateアクションでTweet.createされたあと、
model/tweet.rbでActiveRecordの『after_create』というコールバックを使用し、データベースに保存される直前にTagsテーブルに『#』タグ以下を登録させる感じでやっていきます。
after_create等のコールバックについては、下記のサイトを参考にしました。

Railsガイド

それではいざ、実装。

Tweet Modelにコールバックの記述

after_create do 〜 endの間に処理を記述していきます。
1. controller側でcreateしたTweetを取得
2. Tweetのtextカラムの値から、『#〇〇〇』に該当する箇所を検出
3. tagsテーブルに保存

加えて、view側で『#〇〇〇』をtagsテーブル経由で表示させまます。

4.『#〇〇〇』を含む形でtweetsテーブルに保存されているので、viewで出力する際に正規表現を使って取り除く。

コードは以下の通りです。

models/tweet.rb
class Tweet < ApplicationRecord
  has_many :tweet_tags
  has_many :tags, through: :tweet_tags
  mount_uploader :image, ImageUploader

  #DBへのコミット直前に実行
  after_create do
    #1.controller側でcreateしたTweetを取得
    tweet = Tweet.find_by(id: self.id)
    #2.正規表現を用いて、Tweetのtext内から『#○○○』の文字列を検出
    tags  = self.text.scan(/[##][\w\p{Han}ぁ-ヶヲ-゚ー]+/)
    #3.mapメソッドでtags配列の要素一つ一つを取り出して、先頭の#を取り除いてDBへ保存する
    tags.uniq.map do |t|
      tag = Tag.find_or_create_by(name: t.downcase.delete('#'))
      tweet.tags << tag
    end
  end
end
tweets/index.html.erb
<div class="content">
  <% @tweets.each do |tweet| %>
    <div class="content__post">
      <%=image_tag "#{tweet.image}"%>
      <div class="content__post__tags">
        <!--4.gsub()で正規表現に合致する箇所を空欄にする-->
        <%= simple_format(tweet.text.gsub!(/[##][\w\p{Han}ぁ-ヶヲ-゚ー]+/, "")) %>
        <!--4.tweetにタグがあればタグを出力する-->
        <% if tweet.tags.any? %>
          <% tweet.tags.each do |tag| %>
            <p>#<%= tag.name %></p>
          <% end %>
        <% end %>
      </div>
    </div>
  <% end %>
</div>
<div class="footer">
</div>

index view側でハッシュタグとともにtweetを表示させることができました。
Image from Gyazo
DBにもちゃんと保存されていますね。
めでたしめでたし。
スクリーンショット 2019-12-19 15.27.44.png
スクリーンショット 2019-12-19 15.27.58.png
スクリーンショット 2019-12-19 15.28.15.png

おわりに

今回はTwitte○もどきのアプリでハッシュタグ機能の実装にチャレンジしてみました。
View側で表示させる時に正規表現を使っているところが不恰好なのでヘルパーに突っ込んでもいいかもしれませんね。

応用としては、ハッシュタグからリンクを飛ばして紐づいたtweetを一覧表示できる・・・・・・とかですかね。
ぜひチャレンジしてみてください。

おわり。

12
10
0

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
12
10