今日やったこと18
第14章 ユーザーをフォローする
14.1 Relationshipモデル
ユーザーをフォローする機能を実装するために、Relationshipデータモデルを作成する。
relationships | |
id | integer |
follower_id | integer |
followed_id | integer |
created_at | datetime |
updated_at | datetime |
$ rails generate model Relationship follower_id:integer followed_id:integer
relationshipsテーブルにインデックスを追加し、データベースのマイグレーションを行う。
db/migrate/[timestamp]_create_relationships.rb class CreateRelationships < ActiveRecord::Migration[5.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
$ rails db:migrate
User/Relationshipの関連付け
app/models/user.rb class User < ApplicationRecord has_many :microposts, dependent: :destroy has_many :active_relationships, class_name: "Relationship", foreign_key: "follower_id", dependent: :destroy . . . end
app/models/relationship.rb class Relationship < ApplicationRecord belongs_to :follower, class_name: "User" belongs_to :followed, class_name: "User" end
Relationshipのバリデーション
今の時点では生成されたRelationship用のfixtureファイルは空にしておく。
test/models/relationship_test.rb require 'test_helper' class RelationshipTest < ActiveSupport::TestCase def setup @relationship = Relationship.new(follower_id: users(:michael).id, followed_id: users(:archer).id) end test "should be valid" do assert @relationship.valid? end test "should require a follower_id" do @relationship.follower_id = nil assert_not @relationship.valid? end test "should require a followed_id" do @relationship.followed_id = nil assert_not @relationship.valid? end end
app/models/relationship.rb class Relationship < ApplicationRecord belongs_to :follower, class_name: "User" belongs_to :followed, class_name: "User" validates :follower_id, presence: true validates :followed_id, presence: true end
フォローしているユーザー
Userモデルにfollowingの関連付けを追加する。
app/models/user.rb class User < ApplicationRecord has_many :microposts, dependent: :destroy has_many :active_relationships, class_name: "Relationship", foreign_key: "follower_id", dependent: :destroy has_many :following, through: :active_relationships, source: :followed # 追加 . . . end
followingで取得した集合をより簡単に取り扱うために、followやunfollowといったメソッドを追加する。
追加するメソッドはまずテストから先に書いていく。
test/models/user_test.rb require 'test_helper' class UserTest < ActiveSupport::TestCase . . . # following” 関連のメソッドをテスト test "should follow and unfollow a user" do michael = users(:michael) archer = users(:archer) assert_not michael.following?(archer) michael.follow(archer) assert michael.following?(archer) michael.unfollow(archer) assert_not michael.following?(archer) end end
この時点でテストは失敗するので、次にfollowing関連のメソッドを追加する。
app/models/user.rb class User < ApplicationRecord . . . def feed . . . end # ユーザーをフォローする def follow(other_user) active_relationships.create(followed_id: other_user.id) 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
再びテストをして成功。