第14章ユーザーをフォローする
他のユーザーをフォロー(およびフォロー解除)できるソーシャルな仕組みの追加と、
フォローしているユーザーの投稿をステータスフィードに表示する機能を追加します。
ここで学んだデータモデルは、今後自分用のWebアプリケーションを開発するときに必ず役に立ちます。
14.1 Relationshipモデル
ユーザーをフォローする機能を実装する第一歩は、データモデルを構成することです。ただし、これは見た目ほど単純ではありません。
素朴に考えれば、has_many
(1対多) の関連付けを用いて「1人のユーザーが複数のユーザーをhas_many
としてフォローし、1人のユーザーに複数のフォロワーがいることをhas_many
で表す」といった方法でも実装できそうです。しかし後ほど説明しますが、この方法ではたちまち壁に突き当たってしまいます。これを解決するためのhas_many through
についてもこの後で説明します。
14.1.1 データモデルの問題 (および解決策)
あるユーザーをフォローしているすべてのユーザーの集合はfollowersとなりuser.followersはそれらのユーザーの配列を表すことになります。
Twitterの慣習にならい、本チュートリアルではfollowingという
呼称を採用します (例: “50 following, 75 followers”)。
したがって、あるユーザーがフォローしているすべてのユーザーの集合はcalvin.followingとなります。
followingテーブルと has_many関連付けを使って、
フォローしているユーザーのモデリングができます。
user.followingはユーザーの集合でなければならないため、
followingテーブルのそれぞれの行は、followed_idで識別可能なユーザーでなければなりません (これはfollower_idの関連付けについても同様です)。
さらに、それぞれの行はユーザーなので、
これらのユーザーに名前やパスワードなどの属性も追加する必要があるでしょう。
2つの疑問が生じます。
1. あるユーザーが別のユーザーをフォローするとき、何が作成される? 2. あるユーザーが別のユーザーをフォロー解除するとき、何が削除される?。
1人のユーザーは1対多の関係を持つことができ、
さらにユーザーはリレーションシップを経由して多くのfollowing
(またはfollowers) と関係を持つことができるということです。
Facebookのような友好関係 (Friendships) では本質的に
左右対称のデータモデルが成り立ちますが、
Twitterのようなフォロー関係では左右非対称の性質があります。
すなわち、CalvinはHobbesをフォローしていても、
HobbesはCalvinをフォローしていないといった関係性が成り立つのです。
左右非対称な関係性を見分けるために、
それぞれを能動的関係 (Active Relationship)と
受動的関係 (Passive Relationship)と呼ぶことにします
CalvinがHobbesをフォローしているが、
HobbesはCalvinをフォローしていない場合では、
CalvinはHobbesに対して「能動的関係」を持っていることになります。
つまりアイドルとファンの関係のようなものでCalvinはアイドルなわけよ
逆に、HobbesはCalvinに対して「受動的関係」を持っていることになります。
つまりアイドルとファンの関係のようなものでHobbesはファンなわけよ
フォローしているユーザーを生成するために、能動的関係に焦点を当てていきます
フォローしているユーザーはfollowed_idがあれば識別することができるので、
先ほどのfollowingテーブルをactive_relationshipsテーブル
と見立ててみましょう。
ただしユーザー情報は無駄なので、ユーザーid以外の情報は削除します。そして、followed_idを通して、
usersテーブルのフォローされているユーザーを見つけるようにします。
テーブル名にはこの「関係」を表す「relationships」を使いましょう。モデル名はRailsの慣習にならって、Relationshipとします。