Ruby
Rails
Railsチュートリアル

Railsチュートリアル第14章でアホみたいにハマった独学者の備忘録 part2

前回の記事に続き、またハマりました。

ハマったところ

Follow機能とUnfollow機能のバックエンドの実装部分。
すでにビューの部分(Followボタン、Unfollowボタン)はできている。

コントローラーでUnfollowされるユーザー情報を取得するところに疑問が生まれ、
考え込んでしまった。

controllerに、ユーザーをFollowするcreateアクションと
Unfollowするdestroyアクションを追加するのですが、そのアクションの中身の部分です。
以下にコード示します。

疑問になったコード

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)
    redirect_to user
  end

  def destroy
    user = Relationship.find(params[:id]).followed
    current_user.unfollow(user)
    redirect_to user
  end
end

上記コードのdestroyアクションでは
user = Relationship.find(params[:id]).followed
で変数userを取得し、unfollowメソッドの引数として利用しています。
URLに含まれているparams[:id]でRelationshipモデルのidを検索しているんです。
え、なんで?① followed_idを検索するところじゃないの??
え、なんで?② find(params[:id])ってparams[:id]followed_idカラムを検索するって意味だっけ??

目には見えないrelationshipモデルを取り巻く情報の流れが頭に構築できていなかったんですね。
次の項で解決に至った箇所を示します。

viewファイルのerb(埋め込みルビー)が解決の糸口に

Unfollowボタンを表示するパーシャルコードを以下に示します。

app/views/users/_unfollow.html.erb
<%= form_for(current_user.active_relationships.find_by(followed_id: @user.id),
             html: { method: :delete }) do |f| %>
  <%= f.submit "Unfollow", class: "btn" %>
<% end %>

このコードが生成するHTMLは以下です。

<form class="edit_relationship" id="edit_relationship_90" action="/relationships/90" accept-charset="UTF-8" method="post">
  <input name="utf8" type="hidden" value="✓">
  <input type="hidden" name="_method" value="delete">
  <input type="hidden" name="authenticity_token" value="RRvQ5/IIXUuXjUCJzhpDrXBtFOZ6gTHkonrkOn3wFO4SJPNMPwTESu0+8dB+QeSfI8+14AUbgLDOzRalKq3YBw==">
  <input type="submit" name="commit" value="Unfollow" class="btn" data-disable-with="Unfollow">
</form>

action=の部分が/relationships/90なのでparams[:id]=90でdeleteメソッドすることになってます。

解決!

あー、followしたりunfollowしたりする度に、その関係性をRelationshipモデルに生成しているんですね。
FollowボタンとUnfollowボタンを押した場合、生成されるHTMLのaction属性は、1ずつ増えた:idを有するURLになっていました。

Unfollowの流れ
1.Unfollowボタンには、Relationshipモデルのidを含むURLをaction属性にもつHTMLがある
2.params[:id]をidにもつrelationshipを取り出す
3.followedメソッドで、フォローされているユーザーを取り出し、変数userへ代入
4.unfollowメソッドで現在ログインしているユーザーから、userをフォローしているというデータを削除

find(params[:id])じゃフォローしてるやつのデータ取り出せないだろう!と思ってしまったというお話でした。
Railsすごすぎ。