14.2.3 [Following] と [Followers] ページ
フォローしているユーザーを表示するページと、フォロワーを表示するページは、
いずれもプロフィールページとユーザー一覧ページを合わせたような作りになるという点で似ています。
どちらにもフォローの統計情報などのユーザー情報を
表示するサイドバーと、ユーザーのリストがあります。
さらに、サイドバーには小さめのユーザープロフィール画像のリンクを格子状に並べて表示する予定です。
フォローしているユーザーのリンクとフォロワーのリンクを
動くようにすることでTwitterに倣って、
どちらのページでもユーザーのログインを要求するようにします。
フォローしているユーザーのリンクとフォロワーのリンクを動くようにすることです。 Twitterに倣って、どちらのページでもユーザーのログインを要求するようにします。そこで前回のアクセス制御と同様に、まずはテストから書いていきましょう。
フォロー/フォロワーページの認可をテストする red
test/controllers/users_controller_test.rb
require 'test_helper' class UsersControllerTest < ActionDispatch::IntegrationTest def setup @user = users(:michael) @other_user = users(:archer) end . . . test "should redirect following when not logged in" do get following_user_path(@user) assert_redirected_to login_url end test "should redirect followers when not logged in" do get followers_user_path(@user) assert_redirected_to login_url end end
この実装には1つだけトリッキーな部分があります。
それはUsersコントローラに2つの新しいアクションを追加する必要があるということです。
定義した2つのルーティングにもとづいており、これらはそれぞれfollowingおよびfollowersと呼ぶ必要があります。
それぞれのアクションでは、タイトルを設定し、ユーザーを検索し、@user.followingまたは@user.followersからデータを取り出し、
ページネーションを行なって、ページを出力する必要があります。
followingアクションとfollowersアクション red
app/controllers/users_controller.rb
class UsersController < ApplicationController before_action :logged_in_user, only: [:index, :edit, :update, :destroy, :following, :followers] . . . def following @title = "Following" @user = User.find(params[:id]) @users = @user.following.paginate(page: params[:page]) render 'show_follow' end def followers @title = "Followers" @user = User.find(params[:id]) @users = @user.followers.paginate(page: params[:page]) render 'show_follow' end private . . . end
Railsは慣習に従って、アクションに対応するビューを暗黙的に呼び出します。
例えば、showアクションの最後でshow.html.erbを呼び出す、といった具合です。
renderを明示的に呼び出し、show_followという同じビューを出力しています。つまり、作成が必要なビューはこれ1つです。
renderで呼び出しているビューが同じである理由は、
ERbはどちらの場合でもほぼ同じであり、で両方の場合をカバーできるためです。
↓フォローしているユーザーとフォロワーの両方を表示するshow_followビュー green
app/views/users/show_follow.html.erb
<% provide(:title, @title) %> <div class="row"> <aside class="col-md-4"> <section class="user_info"> <%= gravatar_for @user %> <h1><%= @user.name %></h1> <span><%= link_to "view my profile", @user %></span> <span><b>Microposts:</b> <%= @user.microposts.count %></span> </section> <section class="stats"> <%= render 'shared/stats' %> <% if @users.any? %> <div class="user_avatars"> <% @users.each do |user| %> <%= link_to gravatar_for(user, size: 30), user %> <% end %> </div> <% end %> </section> </aside> <div class="col-md-8"> <h3><%= @title %></h3> <% if @users.any? %> <ul class="users follow"> <%= render @users %> </ul> <%= will_paginate %> <% end %> </div> </div>