2020.02.26

中間テーブルのリレーション(コメント機能、いいね機能)について備忘録

モデルの関連付けで躓いてしまったので、忘れないよう纏めておきます。

 

単純ですが、今のリレーションはこんな感じになっています。

reference型と普通にカラム追加をする場合の違い

中間テーブルに関連付けする際に、各々に紐付くidを生成する必要があります。

その時、reference型で指定する方法と、普通にカラム追加する2パターンあったのですが、どちらも同じ処理っぽい。

どちらでやっても同じですが、reference型で指定したほうが、後からmigrationファイルを確認した際ぱっと見でわかりやすいのかな??

$ rails g model comment content:string user:references image:references

migrationファイル reference型でやる場合↓

def change
  create_table :comments do |t| 
    t.string :content 
    t.references :user, foreign_key: true 
    t.references :image, foreign_key: true
  end 
end

migrationファイル 普通にカラム追加する場合(外部キー制約もつける場合)↓

def change
  create_table :comments do |t|
    t.string :content 
    t.integer :user 
    t.integer :image 
  end 

  add_foreign_key :images, :users 
end

インデックスを付与するメリットは検索が高速になるとのこと。何万行とかになるとその恩恵を受けるらしい。

 

 

投稿された記事についたコメント数をカウントする

例えば今回のように、投稿された記事にそれぞれコメントが付くような仕様の場合、モデルにcounter_cacheを設定することで関連するテーブルのレコード数を取得できるとのこと。(Qiita参照)

comment.rb

class Comment < ApplicationRecord
  belongs_to :user
  belongs_to :image, :counter_cache => true
end

image.rb

class Image < ApplicationRecord
  belongs_to :user
  has_many :comments, dependent: :destroy
end

 

記事と紐づいているコメントを投稿する場合の処理

ルーティングにて、imagesテーブル(記事)の中にcommentsテーブル(コメント)をネストさせています。

images(記事)が投稿されたとき、commentsでコメントできるようになるみたいなイメージ。

Routes.rb

resources :images, only: [:new, :create, :destroy] do
resources :comments, only: [:create]
end

form_withでネストする時、Imageのshowアクションでインスタンス変数を定義します。

images_controller.rb

def show
  @image = Image.find(params[:id])
  @comment = @image.comments.build
end

@imageでコメントする記事のIDを取得しています。

@comment@imageに関連したインスタンスを生成します。(buildとnewは意味は同じですが、buildは慣習的に関連付けに使うのがベターらしい)

アクションでインスタンス変数を定義したら、viewファイルにフォームを実装していきます。

show.html.erb

<%= form_with(model: [@image, @comment], local: true) do |f| %>
  <%= f.text_area :content, class: "form-control" %>
    <%= button_tag type: "submit", class: "btn btn-success float-right mt-1" do %>
    <i class="fa fa-commenting-o"></i> コメントする
  <% end %>
<% end %>

model: [@image, @comment]でネストすれば、個々の記事に対してコメントを付けることができるようになります。

 

ややこしくて落とし込むのに苦労しましたがなんとかアウトプットしてみました。まだ関連付けについて書いていないことはあるので、後々追記していく予定です!