これまでのあらすじ
はじまりがあればおわりがあるとはよく言ったもので、ながらく続いたこの旅路も終わりを迎えます。この旅路で得たものはなんなのか?その結論をようやく下せるような気がします。
冒頭文章を書いたときすげーまじめなこと書いているって思ったんですけど "あらすじ" じゃなかった……。そんなわけで前回はマイクロポスト関連をつくりました。今回はフォロー機能をつくります。
ユーザをフォローする
まずは、フォロー関係のモデルをつくるためにRelationshipモデルをつくります。
$ rails generate model Relationship follower_id:integer followed_id:integer $ rails db:migrate
なんか文章読んでいたら色々構造がぐちゃぐちゃしてきたんで雑にざっくりER図でまとめてみた。
割とシンプルになった気がする。正しいのかは知らんけどノリ的にはそんな感じな気がしている。ぶっちゃけるとER図つくれるツール見つけたから試してみたかったってだけなんだけどね…。
利用ツール
Flowchart Maker & Online Diagram Software
そうしたらERBとかをなんやかんやいじってフォロワー数などを表示させるようにします。
いじった箇所 | 説明 |
---|---|
config/routes.rb | Relationshipリソース用のルーティングを追加 |
app/models/user.rb | フォローユーザ関連のメソッドの実装 |
app/models/relationship.rb | Relationshipモデルに対してバリデーションなどを追加 |
app/views/static_pages/home.html.erb | ホーム画面に統計情報表示 |
app/views/users/show_follow.html.erb | フォローしているユーザーとフォロワーの両方を表示 |
app/views/users/show.html.erb | フォロワーの統計情報を追加 |
app/views/users/_follow_form.html.erb | フォロー/フォロー解除フォームのパーシャル |
app/views/users/_follow.html.erb | ユーザーをフォローするフォーム |
app/views/users/_unfollow.html.erb | ユーザーをフォロー解除するフォーム |
app/assets/stylesheets/custom.scss | CSSカスタマイズ |
とまあそんなところをいじっていきます。ほぼほぼガワをいじってますね……。
フォローボタンの機能を実装しよう
これ作ります。
$ rails generate controller Relationships
# app/controllers/relationships_controller.rb class RelationshipsController < ApplicationController before_action :logged_in_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
わざわざリダイレクトするのを避け、Ajax対応させるためにform_for ..., remote: true
とか使います。Railsだとform_for ..., remote: true
とかにするだけで対応できるそうですね。
修正箇所 | 説明 |
---|---|
app/views/relationships/create.js.erb | フォローの関係性を作成する |
app/views/relationships/destroy.js.erb | フォローの関係性を削除する |
app/controllers/relationships_controller.rb | リレーションシップのアクセス制御 |
Ajax関連参考
Rails で JavaScript を使用する | Rails ガイド
ステータスフィードをつくろう
以下機能を書き書きしてステータスフィードを実装します。
# app/models/user.rb class User < ApplicationRecord ### 略 ### # ユーザーのステータスフィードを返す def feed following_ids = "SELECT followed_id FROM relationships WHERE follower_id = :user_id" Micropost.where("user_id IN (#{following_ids}) OR user_id = :user_id", user_id: id) end ### 略 ### end
割とSQLの直書きって抵抗あるんですけど、クエリビルダも万能じゃないから複雑になったらこう使うよってことでいいんですかね。
そんでテストは以下。
$ rails generate integration_test following
# test/integration/following_test.rb require 'test_helper' class FollowingTest < ActionDispatch::IntegrationTest def setup @user = users(:michael) @other = users(:archer) log_in_as(@user) end test "フォローページ" do get following_user_path(@user) assert_not @user.following.empty? assert_match @user.following.count.to_s, response.body @user.following.each do |user| assert_select "a[href=?]", user_path(user) end end test "フォロワーページ" do get followers_user_path(@user) assert_not @user.followers.empty? assert_match @user.followers.count.to_s, response.body @user.followers.each do |user| assert_select "a[href=?]", user_path(user) end end test "標準的な方法でユーザフォロー" do assert_difference '@user.following.count', 1 do post relationships_path, params: { followed_id: @other.id } end end test "Ajaxでユーザフォロー" do assert_difference '@user.following.count', 1 do post relationships_path, xhr: true, params: { followed_id: @other.id } end end test "標準的な方法でユーザ解除" do @user.follow(@other) relationship = @user.active_relationships.find_by(followed_id: @other.id) assert_difference '@user.following.count', -1 do delete relationship_path(relationship) end end test "Ajaxでユーザ解除" do @user.follow(@other) relationship = @user.active_relationships.find_by(followed_id: @other.id) assert_difference '@user.following.count', -1 do delete relationship_path(relationship), xhr: true end end test "Home のフィード" do get root_path @user.feed.paginate(page: 1).each do |micropost| assert_match CGI.escapeHTML(micropost.content), response.body end end end
第十四章の感想
やっと終わったー。テレビアニメ1クール完走できないことに定評のある僕でもこの長丁場を終わらせることが出来ました。さてさて、内容の方ですが、やっていることはフォロー機能の実装となります。色々とリレーションでごちゃごちゃしてますが、実装内容はシンプルにフォローフラグをオンにするかオフにするかといった感じっぽいです。そこを実装の起点にすればオンオフだけじゃなくてユーザIDも紐づけないとダメやなみたいな感じで必要機能を拡張できると思います。
第14章の感想としてはそんな感じです。総括のほうはまた別の記事にまとめていきたいと思います。
終わり