2
0

More than 1 year has passed since last update.

Rails タグ投稿機能のコード解説

Last updated at Posted at 2022-03-07

モデル作成

$ rails g model Tag tag_name:string                     //Tagモデル作成
 
$ rails g model TagMap post:references tag:references  //TagMapモデル作成

投稿画面

posts/new.html.erb
<%=form_with(model: @post, url: posts_path, local: true) do |f| %>
             <h1>投稿する</h1>
             <%= f.text_field :tag_name%>・・1
             <input type="submit" value="投稿">
<% end %>

コードの解説

1・・<%= f.text_field :tag_name:この行を記述することで、フォームに入力されたタグが、params[:post][:tag_name]というパラメータとしてcreateアクションへ送信される。

コントローラの作成

posts_controller.rb
def create
    @post = Post.new(
      content: params[:content],

      user_id: @current_user.id
    )
     tag_list = params[:post][:tag_name].split(nil)・・1
    if image = params[:post][:image]
      @post.image.attach(image)
    end
    if @post.save
       @post.save_tag(tag_list)・・2
       flash[:notice] = '投稿を作成しました'
       redirect_to('/posts/index')
    else
      render('posts/new')
    end
  end

コードの解説

1・・params[:post][:tag_name]はformから、@postオブジェクトを参照してタグの名前も一緒に送信するのでこの形で取得する。次にsplit(nil)で送信されてきた値を、スペースで区切って配列化する。配列化する理由はあとでこの値をデータベースに保存する際に一つずつ繰り返し処理で取り出す必要があるため。
2・・先ほど取得したタグの配列をデータベースに保存する処理をモデルファイルで行うようにする。
タグで入力した値を配列に収めてる(tag_list)を引数としてモデルファイルに渡す。

Tag_mapモデルファイルの作成

models/tag_map.rb
class TagMap < ApplicationRecord
  belongs_to :post・・1
  belongs_to :tag・・1
  validates :post_id, presence: true・・2
  validates :tag_id, presence: true・・2
end

コードの解説

1・・複数のPost、複数のTagに所有されるのでbelongs_toで関連付けを行う。
2・・PostとTagの関係を構築する際、2つの外部キーが存在しなければならないのでvalidatesの記述を書きます。

Tagモデルファイルの作成

models/tag.rb
class Tag < ApplicationRecord
  has_many :tag_maps, dependent: :destroy, foreign_key: 'tag_id'
  has_many :posts, through: :tag_maps
end

コードの解説

tag_mapsテーブルとの関連付けを行ってから、tag_mapsを通してpostsテーブルと関連づけています。Tag.postsとすれば、タグに紐付けられたPostを取得できる。

Postモデルファイルの作成

models/post.rb
class Post < ApplicationRecord
   has_many :tag_maps, dependent: :destroy
  has_many :tags, through: :tag_maps
 

  def save_tag(sent_tags)
    current_tags = tags.pluck(:tag_name) unless tags.nil?・・1
    old_tags = current_tags - sent_tags・・2
    new_tags = sent_tags - current_tags・・3

    old_tags.each do |old|
      tags.delete Tag.find_by(tag_name: old)・・4
    end

    new_tags.each do |new|
      new_post_tag = Tag.find_or_create_by(tag_name: new)・・5
      tags << new_post_tag・・5
    end
  end
end

コードの解説

1・・先ほどcreateアクションにて保存した@postに紐付いているタグが存在する場合、タグの名前を配列として全て取得する。
2・・現在取得した@postに存在するタグから、送信されてきたタグを除いたタグをold_tagsとする。
3・・送信されてきたタグから、現在存在するタグを除いたタグをnew_tagsとする。
4・・古いタグを削除する。
5・・新しいタグの保存(tagsにpost_tagを追加して保存)

参考記事

【Rails】gemなしで投稿に対してタグ付けする機能+タグで投稿を絞り込み表示する機能の実装手順
[Ruby on rails]タグ付け機能① 複数のタグ付け
railsのself.tags << post_tagの意味

 

2
0
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
2
0