Edited at

Railsチュートリアル第14章でアホみたいにハマった独学者の備忘録

Railsチュートリアル第14章の 14.1.5 フォロワーの演題で盛大にハマったので備忘録を残します。


14章でどんなことを勉強するのか

Railsチュートリアルでは、Twitteサービスのクローンを作っています。

第14章では、Twtterでいうところのfollowとfollowerの機能を実装しながら勉強します。


どんなところではまったのか

フォローするユーザーとフォローされるユーザーを記録するために、

この章で扱うデータモデルの構成は、以下に示すような関係になっていました。

Userテーブル

id
name
email

1
foo
bar@bar.com

↓ userテーブルのidとfollower_idをthroughで紐づけ

follower_id
followed_id

:kissing_closed_eyes: 1

2

:kissing_closed_eyes: 1

3

3
2

5
2

:kissing_closed_eyes: 1

6

2
2

↓ followed_idでuser.followingという配列を作成する

:has_many

id
name
email

→2
...
...

id
name
email

→3
...
...

id
name
email

→6
...
...


コードで表すと


app/models/user.rb

  has_many :active_relationships,  class_name:  "Relationship",

foreign_key: "follower_id",
dependent: :destroy
has_many :passive_relationships, class_name: "Relationship",
foreign_key: "followed_id",
dependent: :destroy
has_many :following, through: :active_relationships, source: :followed
has_many :followers, through: :passive_relationships, source: :follower

上記の記述により、様々なメソッドが使えるようになります。

active_relationship.follower
フォロワーを返します

active_relationship.followed
フォローしているユーザーを返します

user.active_relationships.create(followed_id: other_user.id)
userと紐付けて能動的関係を作成/登録する

user.active_relationships.create!(followed_id: other_user.id)
userを紐付けて能動的関係を作成/登録する (失敗時にエラーを出力)

user.active_relationships.build(followed_id: other_user.id)
userと紐付けた新しいRelationshipオブジェクトを返す

Railsが作ってくれたメソッドに加えて、チュートリアルでは以下のようなメソッドも定義しました。


app/models/user.rb

class User < ApplicationRecord

.
.
.
def feed
.
.
.
end

# ユーザーをフォローする
def follow(other_user)
following << other_user
end

# ユーザーをフォロー解除する
def unfollow(other_user)
active_relationships.find_by(followed_id: other_user.id).destroy
end

# 現在のユーザーがフォローしてたらtrueを返す
def following?(other_user)
following.include?(other_user)
end

private
.
.
.
end



演習課題は?

やっとここまでこれました。以下問題文。

コンソールを開き、何人かのユーザーが最初のユーザーをフォローしている状況を作ってみてください。最初のユーザーをuserとすると、user.followers.map(&:id)の値はどのようになっているでしょうか?

1.コンソール開いて、適当な変数名(user1, user2, user3)にUserテーブルの適当な値(User.firstとか)を代入

2.user2.follow(user1)でもいいし、railsがつくった user1.active_relationships.create(user2)でもいいからフォローとフォロワーを作成

3.user1.followers.map(&:id)でfollowerになったuserのidを配列で出力

できない...。

** 原因 **

follower_idとRelationテーブルのヒモ付を間違えてた。

正しいコードは


app/models/user.rb

  has_many :passive_relationships, class_name:  "Relationship",

foreign_key: "followed_id",
dependent: :destroy

has_many :followers, through: :passive_relationships, source: :follower


間違えたコード has_many の through: にactive_relationships渡してる...


app/models/user.rb

  has_many :passive_relationships, class_name:  "Relationship",

foreign_key: "followed_id",
dependent: :destroy

has_many :followers, through: :active_relationships, source: :follower


解決まで時間かかりました。コードのミスって治すのが本当に難しいですね...

followメソッドが悪いのかな?user.active_relationships.createならいけるかも!とか

コンソールで試行錯誤したらこんな落ちでしたとさ!

Railsチュートリアル同じようにつまった人いたらこれが参考になりますように!