0
0

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 3 years have passed since last update.

フォロー機能実装で詰まったところ

Last updated at Posted at 2020-06-18

find_or_create_byメソッド

def follow(other_user)
  unless self == other_user #フォローしようとしてるother_userが自分ではないか検証
    self.relationships.find_or_create_by(follow_id: other_user.id)
  end
end

引数の条件に該当するデータがあればそれを返すfind_by(other_user)、なければ新規作成create(other_user)
新規作成後、保存する

参考記事:find_or_initialize_byとfind_or_create_byの違いとは?

includesメソッド

def following?(other_user)
  self.followings.include?(other_user)
end
include?メソッドとは?

引数で指定した要素が配列中に含まれてるか判定するメソッド

※selfはuser自身なのでuser。
self(自分自身)がfollowing(フォローしてる人たち)の中でother_userが含まれてるかどうか判定するってこと。
other_userが含まれていればtrueを返し、含まれてなければfalseを返す。

relationshipモデルのマイグレーションファイル

class CreateRelationships < ActiveRecord::Migration[5.2]
  def change
    create_table :relationships do |t|
      t.integer :follower_id
      t.integer :following_id

      t.timestamps null: false

      add_index :relationships, :follower_id
      add_index :relationships, :following_id
      add_index :relationships, [:follower_id, :follwing_id], unique: true #follow_idとfollowing_idの同じ組み合わせができないようにする設定
    end
  end
end

add_indexがindexをつけることくらいはわかるが、そもそもindexって何のためにつけるんだっけ?
add_indexの記述の箇所の意味がわからないということでこちらの記事が参考になった。

参考記事:データベースにindexを貼る方法

Q.indexは何のためにつける?

カラムからデータを取得するときに検索しやすいようにするため。例えば今回だったらfollowerカラムからfollwerを検索しやすいようにするため。データが3人だけとかならいらないけど、1万人とかになってくると検索するのに時間がかかるのでつけた方がいいってことみたい。

add_indexの書き方
add_index :テーブル名, カラム名

上の例でいうと、relationテーブルのfollow_idカラム、relationテーブルのfollowing_idカラムってことになる。

userモデルの書き方

user.rb
has_many :follwing_relationships, foreign_key: "follower_id", class_name: "Relationship", dependent: :destroy

follwing_relationshipsモデルは実際には存在しない。あくまで便宜上こういうふうに設定してるだけ。このモデルはフォローしてる人たちのモデル。
なのでfollower_idが外部キーで設定されてる。

class_name: "Relationship"これはさっきも言ったけど、follwing_relationshipsモデルは実際には存在しなくて、実際に存在するのは"Relationship"モデルだから、名前はfollwing_relationshipsってなってるけど、名前だけで本当は"Relationship"のことだよ〜と言ってる。

dependent: :destroyこれは結構単純で、あるuserが無くなったら、そのuserがフォローしてる人たちとのrelationも消えるようにする設定。userモデルとrelationshipモデルは従属関係にあって、userが消えると、そのuserのrelationship(userとfollow_idsの関係)も消えるということ。

user.rb
has_many :follwings, through: :following_relationships

has_many :follwings(モデル名)でモデル間のアソシエーションを定義してる。through: :following_relationshipsこれは中間テーブルを示してる。何度か出てきてるけど、名前はfollowing_relationshipsだけど実際はrelationshipsが中間テーブル。

要は、userモデル(フォローされてる人たち)とuserモデル(フォローしてる人たち)という2つのuserモデルの中間にrelationモデルがあるってこと。

アソシエーションを利用するための2つの条件
  1. モデルクラスにhas_manyやbelongs_toなどのメソッドで関係が定義されている
  2. 所属する側のテーブルに所属するモデル名_idというカラムがある

特に2.は忘れがちなので注意!!
今回だと、following_idが必要ということだけど、上記のマイグレーションファイルのところ見てもらうと、あそこでfollowing_idを入れてあるのがわかると思うけど、今回はそこで定義してるからOK。

user.rb
def following?(other_user) 
  following_relationships.find_by(following_id: other_user.id)
end

def follow!(other_user)
  following_relationships.create!(following_id: other_user.id)
end

def unfollow!(other_user)
  following_relationships.find_by(following_id: other_user.id).destroy
end

find_byメソッドは1件しか返さない。なので、これを設定しておけば、ピンポイントで探したいuserを探せる。
参考記事:【Rails】世界で一番詳しいfind_byメソッドのいろいろな使い方

create!はそのまま保存するって意味。

最後のは1件userを見つけてきて、.destroyメソッドは消すだからそのデータを消すってこと。

僕がまだよく理解できてないのが、なぜモデルにメソッドを書くのか?
普通こういうメソッドはcontrollerに書くものと思ってたけど。
探したらこんな記事見つけた。
Railsのモデルに書いたメソッドってどうやってコントローラで使うの?

それでわかったのが、controllerの記述を出来るだけシンプルにするため。ってことみたい。
確かに上記の記述をcontrollerに書いたらごちゃごちゃしててわかりづらくなりそうだ。

マイグレショーンファイルのエラー

Caused by:Mysql2::Error: Table '(アプリ名)_development.relationships' doesn't exist
「マイグレーション Table doesn't exist」で検索してみたら、この記事が出てきた。
参考記事:Rails5.1に移行後のmigrationファイルの注意

ルーティング

routes.rb
resources :users do
  member do
    get :following, :followers
  end
end
Q.memberって何?どういう意味?

参考記事:railsのroutes.rbのmemberとcollectionの違いをわかりやすく解説してみた。〜rails初心者から中級者へ〜

following_user GET    /users/:id/following(.:format)                                                           users#following
followers_user GET    /users/:id/followers(.:format)                                                           users#followers

URLを見てもらうとわかるように、:idが自動で追加されるようになる。

relationshipモデルのidが空になってるというエラー

スクリーンショット 2020-06-20 06.55.37.png

user.rb
has_many :following_relationships, class_name: "Relationship", foreign_key: "follower_id", dependent: :destroy

def following?(other_user)
  following_relationships.find_by(following_id: other_user.id)
end

following_relationshipsはRelationshipモデルを指してる。
following?メソッドはother_userという1人のユーザーを引数にとり、フォローする相手のユーザーがデータベース上に存在するかどうかをチェックする。

今回のエラーは、フォローする相手のuserのidが定義されていなくて空になってるよというエラー。

参考にさせて頂いた記事

railsでフォロー機能をつける。
この記事を見ながらフォロー機能を実装しました。
データベースにindexを貼る方法
find_or_initialize_byとfind_or_create_byの違いとは?
Railsのモデルに書いたメソッドってどうやってコントローラで使うの?

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?