🍎
【Rails】フォロー機能実装
はじめに
- アプリケーション作成済
- 「relationshipsコントローラー」「ralationshipモデル」を使用して実装
- 完成イメージ ↓
1.Relationshipモデル、relationshipsテーブルを作成
ターミナル
$ rails g model Relationship follower_id:integer followed_id:integer
実行結果として下記が表示されればOK!
ターミナル
Running via Spring preloader in process 11300
invoke active_record
create db/migrate/20230801101147_create_relationships.rb
create app/models/relationship.rb
invoke test_unit
create test/models/relationship_test.rb
create test/fixtures/relationships.yml
ターミナル
$ rails db:migrate
- ここまでで「Relationshipモデル」「relationshipsテーブル」が生成された
- 「follower_id:integer」「followed_id:integer」=カラムを外部キーとして生成
- 「user_id」ではないのはなぜか?
- フォロー機能の場合、userがuserをフォローするため、「Userテーブル同士を結ぶ必要がある」
- このことからフォローする側もフォローされる側も「user_id」となってしまうので、中間テーブルである「relationshipsテーブル」を作成し、「follower_id」「followed_id」を用意した。
2.アソシエーションを設定
app/models/relationship.rb
class Relationship < ApplicationRecord
belongs_to :follower, class_name: "User"
belongs_to :followed, class_name: "User"
end
- 「belongs_to :follower」だと、存在しないfollowersテーブルを探しに行くためエラーが出てしまう
- 「belongs_to :follower, class_name: "User"」とすることで、「usersテーブル」を探しに行くようになる
app/models/user.rb
class User < ApplicationRecord
:
:
#フォローする、フォローされた 関係
#has_many :アソシエーションが繋がっているテーブル名, class_name: "モデルの名前", foreign_key: 外部キーとして持っているカラム
has_many :followers, class_name: "Relationship", foreign_key: "follower_id", dependent: :destroy
has_many :followeds, class_name: "Relationship", foreign_key: "followed_id", dependent: :destroy
#フォロー画面一覧用
#has_many :テーブル名, through: :中間テーブル名
#@user.following_users でそのuserがフォローしている人の一覧表示
has_many :following_users, through: :followers, source: :followed
#@user.follower_users でそのuserがフォローされている人の一覧表示
has_many :follower_users, through: :followeds, source: :follower
:
3.Userモデルにメソッドを定義
app/models/user.rb
class User < ApplicationRecord
:
:
#フォローするときの処理
def follow(user_id)
followers.create(followed_id: user_id)
end
#フォローを外すときの処理
def unfollow(user_id)
followers.find_by(followed_id: user_id).destroy
end
#フォローしていればtrueを返す
def following?(user)
following_users.include?(user)
end
end
4.ルーティング設定
- アソシエーション設定で「user」と「Relationship」を繋げたため、user_idを取得できるようにネストする
- createアクション(フォローする)、destroyアクション(フォローをはずす)を記述
config/routes.rb
Rails.application.routes.draw do
:
resources :users, only: [:index, :show, :edit, :update ] do
member do
get :follows, :followers
end
resource :relationships, only: [:create, :destroy]
end
:
ターミナル
$ rails routes
でルーティングを確認!
ターミナル
user_relationships DELETE /users/:user_id/relationships(.:format) relationships#destroy
POST /users/:user_id/relationships(.:format) relationships#create
- ルーティングに「:user_id」が含まれている!
5.コントローラー作成
relationshipsコントローラーを作成
ターミナル
$ rails g controller relationships
ルーティングで設定したcreate、destroyアクションを記述
app/controllers/relationships_controller.rb
class RelationshipsController < ApplicationController
def create
end
def destroy
end
end
6.アクションを実装
app/controllers/relationships_controller.rb
class RelationshipsController < ApplicationController
#フォローする
def create
current_user.follow(params[:user_id])
redirect_to request.referer
end
#フォローをはずす
def destroy
current_user.unfollow(params[:user_id])
redirect_to request.referer
end
end
app/controllers/users_controller.rb
class UsersController < ApplicationController
:
:
#users/showページでフォロー数、フォロワー数を表示
def show
@user = User.find(params[:id])
@book = Book.new
@books = @user.books
@following_users = @user.following_users
@follower_users = @user.follower_users
end
#フォロー一覧
def follows
user = User.find(params[:id])
@users = user.following_users
end
#フォロワー一覧
def followers
user = User.find(params[:id])
@user = user.follower_users
end
:
7.ビュー作成
users/showページに実装
app/views/users/show.html.erb
<tr>
<th>Follows</th>
<td>
<%= link_to follows_user_path(user) do %>
<h6><%= user.followers.count %></h6>
<% end %>
</td>
</tr>
<tr>
<th>Followers</th>
<td>
<%= link_to followers_user_path(user) do %>
<h6><%= user.followeds.count %></h6>
<% end %>
</td>
</tr>
<tr>
<td>
<% if current_user != user %> #ログインしているuserにフォローボタンは表示されない
<% if current_user.following?(user) %>
<%= link_to "フォロー外す", user_relationships_path(user.id), method: :delete, class: "btn btn-danger" %>
<% else %>
<%= link_to "フォローする", user_relationships_path(user.id), method: :post, class: "btn btn-success" %>
<% end %>
<% end %>
</td>
</tr>
フォロー数、フォロワー数が表示された!
users/indexページにも実装
app/views/users/index.html.erb
<% @users.each do |user| %>
<tr>
<td><%= image_tag user.get_profile_image(100, 100) %></td>
<td><%= user.name %></td>
<td><%= link_to "show", user_path(user.id) %></td>
<td>フォロー<%= user.followers.count %></td> #フォロー数表示
<td>フォロワー<%= user.followeds.count %></td> #フォロワー数表示
<td>
<% if current_user.following?(user) %> #フォローしていたら表示
<%= link_to "フォロー外す", user_relationships_path(user.id), method: :delete, class:"btn btn-danger" %>
<% else %>
<%= link_to "フォローする", user_relationships_path(user.id), method: :post, class:"btn btn-success" %> #フォローしていなかったら表示
<% end %>
</td>
</tr>
<% end %>
フォロー数、フォロワー数が表示された!
8.フォロー、フォロワー 一覧ページを作成
app/views/usersに「followers.html.erb」「follows.html.erb」ファイルを作成
app/views/users/followers.html.erb
<h2>Follows</h2>
<table class="table">
<thead>
<tr>
<th>Image</th>
<th>name</th>
<th colspan="2"></th>
</tr>
</thead>
<tbody>
<% @user.each do |user| %>
<tr>
<td>
<%= link_to user_path(user) do %>
<%= image_tag user.get_profile_image(50, 50) %>
<% end %>
</td>
<td><%= user.name %></td>
<td>
<%= link_to follows_user_path(user) do %>
<h6>フォロー<%= user.followers.count %></h6>
<% end %>
</td>
<td>
<%= link_to followers_user_path(user) do %>
<h6>フォロワー<%= user.followeds.count %></h6>
<% end %>
</td>
</tr>
<% end %>
</tbody>
</table>
app/views/users/follows.html.erb
<h2>Follows</h2>
<table class="table">
<thead>
<tr>
<th>Image</th>
<th>name</th>
<th colspan="2"></th>
</tr>
</thead>
<tbody>
<% @users.each do |user| %>
<tr>
<td>
<%= link_to user_path(user) do %>
<%= image_tag user.get_profile_image(50, 50) %>
<% end %>
</td>
<td><%= user.name %></td>
<td>
<%= link_to follows_user_path(user) do %>
<h6>フォロー<%= user.followers.count %></h6>
<% end %>
</td>
<td>
<%= link_to followers_user_path(user) do %>
<h6>フォロワー<%= user.followeds.count %></h6>
<% end %>
</td>
</tr>
<% end %>
</tbody>
</table>
フォロー一覧ページ
フォロワー一覧ページ(まだフォローされてないのでuserの表示なしの状態)
以上でフォロー機能の実装が完了となります!!
間違っている箇所などありましたら教えていただけると幸いです🙏
Discussion