Rails 総復習1ヶ月チャレンジ 9日目(Railsチュートリアル編)
本日は9日目です!なんだかんだで1週間以上かかる濃い内容だったRailsチュートリアルも今日で最後です!
ではやっていきます!
9日目(Ruby on Rails チュートリアル 14章ユーザーをフォローする)
第14章はユーザーが気に入った他のユーザーをフォローすることができる機能を実装するものです。フォローできるということは他のユーザーからフォローされるということも考えなければなりません。この章で一番重要なのではテーブルをどのように考えるかです。(自分が苦手な部分です)これにはフォローする、フォローされるというところを切り分けて考えると良さそうです。
フォローする、解除する関係について
今までマイクロポストを作成、削除などリソースに関連したことから
あるユーザーが別のユーザーをフォローする(◯◯を作成)、あるユーザーが別のユーザーのフォロー解除をする(◯◯を削除)
◯◯の部分を考える必要があります。
これを考えると2人のユーザーの「関係(リレーションシップ)」と考えるとしっくりきます。したがってユーザー間の関係性を示すRelationshipモデルを作成すれば良さそうです。
自分がフォローする側(能動的な部分)の考え方(active_relationships)
(Railsチュートリアル スライド : 第14章 ユーザーをフォローするより引用)
実装
$ rails generate model Relationship follower_id:integer followed_id:integer
#db/migrate/[timestamp]_create_relationships.rb class CreateRelationships < ActiveRecord::Migration[6.0] def change create_table :relationships do |t| t.integer :follower_id t.integer :followed_id t.timestamps end add_index :relationships, :follower_id add_index :relationships, :followed_id add_index :relationships, [:follower_id, :followed_id], unique: true end end
- マイグレーションファイルにadd_indexを使う
データベースに問い合わせした時に、よく使うデータは高速化させることができる。 フォローしている数 フォロワーの数 複合キーインデックス(複数のカラムで検索)→follower_idとfollowed_idの組み合わせが必ずユニークであることを保証する仕組みです。これにより、あるユーザーが同じユーザーを2回以上フォローすることを防ぎます。
- referencesが使えない理由
"{モデル名}_id"のようになり、規約に乗っ取っていない、follwer, followedクラスがある前提で作られてしまう
- Userモデルのアソシエーション
class User < ApplicationRecord has_many :microposts, dependent: :destroy #デフォルトで設定されている class_name: "Micropost" #デフォルトで設定されている foreign_key: "user_id" has_many :active_relationships, class_name: "Relationship", foreign_key: "follower_id", dependent: :destroy : end
今回は参照するclassと、外部キーを自分で設定する必要があります。class_name: "Relationship"とforeign_key: "follower_id"部分がその設定の記述です。
- Relationshipモデル
class Relationship < ApplicationRecord belongs_to :follower, class_name: "User" #followerというclassは存在しない為にclass_name: "User"の記述が必要 belongs_to :followed, class_name: "User" #followedというclassは存在しない為にclass_name: "User"の記述が必要 end
- Userモデルにフォローしたユーザーの集合を取得するメソッド(following)を記載
class User < ApplicationRecord has_many :microposts, dependent: :destroy #デフォルトで設定されている class_name: "Micropost" #デフォルトで設定されている foreign_key: "user_id" has_many :active_relationships, class_name: "Relationship", foreign_key: "follower_id", dependent: :destroy has_many :following, through: :active_relationships, source: :followed : end
この部分
has_many :following, through: :active_relationships, source: :followed
これは下記を簡潔に使えるようにしています。
@user.active_relationships.map(&:followed)
簡潔に使えるようになる。
@user.following
ここでは
has_manyで新しくfollowingというメソッドを宣言。
followingメソッドの役割は、Userクラスのインスタンスオブジェクトに対してactive_relationshipsメソッドを呼び出し、その返ってきたデータの集合に対してfollowedメソッドを一つずつ実行します。これでフォロワーがフォローされている側の情報を取得できます。
次にフォロワーを考える (受動的、passive_relationships)
(Railsチュートリアル スライド : 第14章 ユーザーをフォローするより引用)
実装(Relationshipsモデルはactive_relationshipsの際に実装済み)
- Userモデルのアソシエーション
class User < ApplicationRecord has_many :microposts, dependent: :destroy 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 . . . end
ここの流れは、
has_manyで新しくfollowersというメソッドを宣言。
followersメソッドの役割は、Userクラスのインスタンスオブジェクトに対してpassive_relationshipsメソッドを呼び出し、その返ってきたデータの集合に対してfollowerメソッドを一つずつ実行します。これでフォローされている側がフォロワーの情報を取得できます。
「||=」とは何か?
フォロワーの統計情報を表示するパーシャルで下記のような表記がありました。
<% @user ||= current_user %>
これは元々下記のコードを短縮したものです。
<% @user = @user || current_user %>
Rubyでは、||演算子をいくつも連続して式の中で使う場合、項を左から順に評価し、最初にtrueになった時点で処理を終えるように設計されています。nilは論理値はfalseです。
今回の場合、パーシャルを呼び出すのはHomeページとUser詳細ページなので、Homeページでパーシャルを呼び出した場合は@userはnilとなるので代わりにcurrent_userが代入されます。User詳細ページの場合、@userはnilではないので何も代入されません。
今回は以上です!明日からはスクール課題の復習編です!