#①Model(3ステップ)
###○必要なモデル(2つ)を作成
1. USER (deviseで作成)
2. Relationships
rails g model Relationship follower_id:integer followed_id:integer
create_table "relationships", force: :cascade do |t|
t.integer "follower_id"
t.integer "followed_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
###○アソシエーション
各モデルに追記。
####Relationshipモデル [ Relationships.rb ]
belongs_to :follower, class_name: "User"
belongs_to :followed, class_name: "User"
*class_name: "モデル名" で、指定したモデルを参照した際のモデル名を変更できる。
Userモデルを「Follower」と「Followed」に分けるイメージ。
####Userモデル [ User.rb ]
# フォローしている
has_many :follower, class_name: "Relationship", foreign_key: "follower_id", dependent: :destroy
# フォローされてる
has_many :followed, class_name: "Relationship", foreign_key: "followed_id", dependent: :destroy
#フォローしている人
has_many :follower_user, through: :followed, source: :follower
#フォローされている人
has_many :following_user, through: :follower, source: :followed
Relationshipモデルも「follower」と「followed」に分けられる
foreign_keyを追加することで、それぞれRelationshipモデルを通して取得可能となる
それぞれsourceにしているモデルを通して
*through: :モデル名 指定したモデルを通して取得する
*source: :モデル名 関連するモデルを指定する
###○メソッド定義(3つ) [ User.rb ]
# 1. followメソッド = フォローする
def follow(user_id)
follower.create(followed_id: user_id)
end
# 2. unfollowメソッド = フォローを外す
def unfollow(user_id)
follower.find_by(followed_id: user_id).destroy
end
# 3. followingメソッド = 既にフォローしているかの確認
def following?(user)
following_user.include?(user)
end
htmlで表示を条件分岐する際に使います。
引数にuserが含まれていた場合、trueを返す=trueのときは「フォローを外す」を表示
*.include?(引数)メソッド: 対象の文字列に引数で指定した文字列が含まれているか検索して真偽値を返す
#②Controller
###○メソッド定義: Relationships Controller
def create #フォローする Userモデルで定義したfollowメソッド
current_user.follow(params[:user_id])
redirect_to request.referer #遷移前のURLを取得してリダイレクト
end
def destroy #フォローを外す Userモデルで定義したunfollowメソッド
current_user.unfollow(params[:user_id])
redirect_back(fallback_location: root_path)
end
def follower #follower一覧
user = User.find(params[:user_id])
@users = user.following_user
# .follower_userメソッド :Userモデルで定義済
end
def followed #followed一覧
user = User.find(params[:user_id])
@users = user.follower_user
# .follower_userメソッド :Userモデルで定義済
end
#③Routing
create(follow)、destroy(unfollow)とfollows,followersの一覧用を追加
resources :users
resource :relationships, only:[:create, :destroy]
get 'follows' => 'relationships#follower'
get 'followers' => 'relationships#followed'
end
#④View
###・フォローボタン(follow/unfollow)
フォローボタンを表示させたい部分にリンクを追加
<% if current_user != user %>
<% if current_user.following?(user) %>
<%= link_to 'フォロー外す', user_relationships_path(user.id), method: :delete, class: "btn btn-default" %>
<% else %>
<%= link_to 'フォローする', user_relationships_path(user.id), method: :POST , class: "btn btn-primary"%>
<% end %>
<% end %>
###・follower.follows一覧
relationshipsのなかに、follower.html.erb と follows.html.erbファイルを作成し、
各ファイルに下記の通り記載
<% if @users.count > 0 %> の条件分岐でUserがいる場合はeach文で表示し、
いない場合は ユーザーはいません を表示
<% if @users.count > 0 %>
<table class="table">
<thead>
<tr>
<th>name</th>
</tr>
</thead>
<tbody>
<% @users.each do |user| %>
<tr>
<td><%= @user.name %></td>
<td>フォロー数:<%= @user.follower.count %></td>
<td>フォロワー数:<%= @user.followed.count %></td>
<td>
<% if current_user != @user %>
<% if current_user.following?(@user) %>
<%= link_to 'フォロー外す', user_relationships_path(@user.id), method: :delete, class: "btn btn-default" %>
<% else %>
<%= link_to 'フォローする', user_relationships_path(@user.id), method: :POST , class: "btn btn-primary"%>
<% end %>
<% end %>
</td>
<td><%= link_to "Show", @user %></td>
</tr>
<% end %>
</tbody>
</table>
<% else %>
<p>ユーザーはいません</p>
<% end %>