RailsTutorial
を参考にフォロー機能をつけました。
簡単にまとめます。
※クラス名・id名は本家と変えたところがあります。
※ところどころ自己流にアレンジしています。ご容赦ください。
Relationshipモデル
ターミナル
$ rails g model Relationship follower_id:integer followed_id:integer
db/migrate/20191128014554_create_relationships.rb
class CreateRelationships < ActiveRecord::Migration[5.2]
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
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モデル
app/models/user.rb
class User < ApplicationRecord
略
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
def follow(other_user)
following << other_user
end
def unfollow(other_user)
active_relationships.find_by(followed_id: other_user.id).destroy
end
def following?(other_user)
following.include?(other_user)
end
end
ルーティング
app/config/locals/routes.rb
Rails.application.routes.draw do
略
resources :users, only: [:show] do
member do
get :following, :followers
end
end
resources :relationships, only: [:create, :destroy]
end
ビュー
app/views/users/_stats.html.haml
- @user ||= current_user
%div
= link_to following_user_path(@user) do
#following
= @user.following.count
= link_to followers_user_path(@user) do
#followers
= @user.followers.count
app/views/users/_follow_form.html.haml
- unless current_user == @user
#follow_form
- if current_user.following?(@user)
= render 'unfollow'
- else
= render 'follow'
app/views/users/_follow.html.haml
= form_for(current_user.active_relationships.build, remote: true) do |f|
= hidden_field_tag :followed_id, @user.id
= f.submit "Follow", class: "btn btn-primary"
app/views/users/_unfollow.html.haml
= form_for(current_user.active_relationships.find_by(followed_id: @user.id), html: { method: :delete }, remote: true) do |f|
= f.submit "Unfollow", class: "btn"
xxx.html.haml
#好きなところへ
= render "stats"
= render "follow_form" if user_signed_in?
以下2つは完全自己流なのでスルーしてください。
following.html.haml
.contents
= render "tweets/side-bar"
.contents__right
.contents__right__tweets
.contents__right__tweets__follows
.contents__right__tweets__follows__user-nickname
= @user.nickname
さん
.contents__right__tweets__follows__text
フォロー中
- @users.each do |user|
.contents__right__tweets__follow-users
%p.contents__right__tweets__follow-users__user
= link_to "#{user.nickname}", user_path(user)
.contents__right__tweets__paginate
= paginate(@users)
followers.html.haml
.contents
= render "tweets/side-bar"
.contents__right
.contents__right__tweets
.contents__right__tweets__follows
.contents__right__tweets__follows__user-nickname
= @user.nickname
さん
.contents__right__tweets__follows__text
フォロワー
- @users.each do |user|
.contents__right__tweets__follow-users
%p.contents__right__tweets__follow-users__user
= link_to "#{user.nickname}", user_path(user)
.contents__right__tweets__paginate
= paginate(@users)
本家はshow_follow.html.erb
というビューファイルを作って、そこにレンダリングしています。
僕はfollowing
followers
2つのビューファイルを作りました。冗長かもしれませんが明確に分けて管理したかったのでこうしました。
コントローラー
relationships_controller.rb
class RelationshipsController < ApplicationController
before_action :authenticate_user!
def create
@user = User.find(params[:followed_id])
current_user.follow(@user)
respond_to do |format|
format.html { redirect_to @user }
format.js
end
end
def destroy
@user = Relationship.find(params[:id]).followed
current_user.unfollow(@user)
respond_to do |format|
format.html { redirect_to @user }
format.js
end
end
end
users_controller.rb
class UsersController < ApplicationController
before_action :authenticate_user!, only: [:following, :followers]
略
def following
@user = User.find(params[:id])
@users = @user.following.page(params[:page]).per(3)
end
def followers
@user = User.find(params[:id])
@users = @user.followers.page(params[:page]).per(3)
end
end
本家大正義RailsTutorial
https://railstutorial.jp/chapters/following_users?version=5.1#cha-following_users
ではまた!