• 雑な生き方を丁寧に記すブログ

プログラミング奮闘備忘録3

前回までで、「日報へのリアクション(いいね!)機能」「リアクションした人の一覧表示機能」をなんとか実装してきた日報管理システム。今回のお題は、「特定のユーザーのフォロー機能」の実装。

1. モデル作成

誰(follower)が誰(followee)をフォローしているかという情報を管理しておく必要があるが、followerもfolloweeも同じemployeesのオブジェクトになるし、一人が複数人をフォローしたり、複数人にフォローされたりする「多:多」の関係になるので、ここは新たにフォロー情報をまとめるテーブルを作るしかない。

ということで、followsテーブルを作る。follower_idもfollowee_idもemployeesテーブル依存。

ER図の書き方は自信ない

2. コントローラの作成

新しく用意するコントローラは、誰かをフォローするためのcreate機能と、フォローを解除するdestroy機能だけでとりあえず事足りるはず。

今回は、ある日報の詳細ページを開いた時に、その日報の作成者のことをフォローする、もしくはフォロー解除するボタンを設置するようにしたい。

イメージ

上のイメージでいうと、followerはログイン中の管理太郎さん、followeeは表示している日報作成者の一般花子さん。ということで、そのようにFollowCreateServletをコーディング。

FollowCreateServlet

followerにはログイン中のユーザー情報を、followeeには表示中のreportオブジェクトに紐づいているEmployeeをスコープから持ってきて入れる。作成日時の情報と合わせて、さっき作ったfollowsテーブルへデータ登録する。

次にフォロー解除の機能も書いておく。followsテーブルからフォロー情報を削除してフォロー解除ということにするので、削除するfollowsオブジェクト(f)を指定しなきゃならない。つまり、上の例で言えば、followerが管理太郎でfolloweeが一般花子になってるオブジェクトをfololowsテーブルから抽出して、それを削除する指示をする。このデータ抽出用に”getAnExistingFollow”というクエリをFollowモデル上に作ることにした。

FollowDestroyServlet
@NamedQuery(
            name = "getAnExistingFollow",
            query = "SELECT f FROM Follow AS f WHERE f.follower =:follower AND f.followee =:followee"
            ),

上記のクエリで、followerの変数にログイン中のユーザー、followeeの変数には表示中のreport情報に紐づいたEmployeeを代入してやれば、削除するべきfollowオブジェクトが特定できる。

3. ビューの修正

これでフォローとフォロー解除の機能自体はできたので、あとは実際に画面上からその操作ができるようにビューファイルを修正していく。フォローボタン/フォロー解除ボタンは日報詳細ページにつけるので、該当するreport/show.jspのHTMLをいじっていくわけだが・・・その前に必要な準備がある。まず、ログイン中のユーザーが自分の日報を見てる時にはフォローボタンは表示させない。これはあまり問題ない。次、フォローボタンかフォロー解除ボタンのどちらを表示させるかは、当たり前だが、ログインユーザーが表示中の日報作成者を既にフォローしているかしていないかで判断する必要がある。そのジャッジをするためのコードを予め用意しておく。

まず、Followモデル上に”getExistingFollowCount”という名前でクエリを作る。followerとfolloweeを指定すれば、該当するfollowオブジェクトの数を数えてくれるクエリ。

@NamedQuery(
            name = "getAnExistingFollow",
            query = "SELECT f FROM Follow AS f WHERE f.follower =:follower AND f.followee =:followee"
            ),

そんでもって、このクエリを使って、ログイン中のユーザーが日報の作成者を既にフォローしているかどうかをチェックする文をReportShowServlet上に作って、その結果をfollow_countという変数としてreport/show.jspに渡すようにする。

long follow_count = em.createNamedQuery("getExistingFollowsCount", Long.class)
                                .setParameter("follower", e)
                                .setParameter("followee", r.getEmployee())
                                .getSingleResult();

follow_countが0であれば、まだフォローしてないということなので、「フォローする」ボタンを表示させる。それ以外なら「フォロー解除」のボタンを表示。(理論上、アプリが正しく機能すれば、follow_countは0か1のどちらかしかありえないが)

実際のreport/show.jsp上のコードは下のような感じ。これでボタンが表示されて、先述のFollowCreateServletもしくはFollowDestroyServletへ必要な情報を飛ばせる。

<c:if test="${sessionScope.login_employee.id != report.employee.id}">
                    <c:choose>
                        <c:when test="${follow_count == 0 || follow_count == null}">
                            <form method="POST" action="<c:url value='/follows/create'/>">
                                <p>
                                <input type="hidden" name="_token" value="${_token}" />
                                <input type="hidden" name="report_id" value="${report.id}">
                                <input type="submit" value="${report.employee.name}さんをフォローする">
                                </p>
                            </form>
                        </c:when>
                        <c:otherwise>
                            <form method="POST" action="<c:url value='/follows/destroy'/>">
                                <p>
                                <input type="hidden" name="_token" value="${_token}" />
                                <input type="hidden" name="report_id" value="${report.id}">
                                <input type="submit" value="${report.employee.name}さんのフォローを解除">
                                </p>
                            </form>
                        </c:otherwise>
                    </c:choose>
                </c:if>

実際に画面の表示はこんな感じ。

follow_count == 0のとき
フォロー中(follow_count == 1)のとき

ひとまずこれで、誰かをフォローする機能は実装完了。ここから、「フォローしている人の日報だけを表示する」機能をつけて初めてこれが活きてくるわけだが、長くなるので、そっちの実装については別記事でまとめることにする。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です