チワワかわいいブログ

RUNTEQでrails勉強する日々の記録

2020/12/22 railsチュートリアル14章最後

resources :users do

ブロックを引数として受けることができる

  resources :users do
    member do
      get :following, :followers
    end
  end

=> /users/1/の中でさらに、/users/1/followingといったルーティングを指定できる。

@user ||= current_user

@user があるときは @user = @user、なければcurrent_user
strong id="following" class="stat"はajax実装用

フォロー用フォーム
<% unless current_user?(@user) %> #現在のユーザーが@userでければ(自分自身でなければ)
  <div id="follow_form">
  <% if current_user.following?(@user) %>
    <%= render 'unfollow' %>
  <% else %>
    <%= render 'follow' %>
  <% end %>
  </div>
<% end %>

<%= render 'unfollow' %> followフォーム内でフォロー/アンフォローの切り替えるができるパーシャルを作成し呼び出す

#フォローフォーム
<%= form_with(model: current_user.active_relationships.build, local: true) do |f| %> #インスタンスを作成してそこにフォームのデータを直接渡すこともできる
  <div><%= hidden_field_tag :followed_id, @user.id %></div> #入力フォームは必要なく、followed_idに@user.id(URLのID)を渡せば良い
  <%= f.submit "Follow", class: "btn btn-primary" %>
<% end %>

#unfollowフォーム
<%= form_with(model: current_user.active_relationships.find_by(followed_id: @user.id),
            html: { method: :delete }, local: true) do |f| %> #フォローしているデータをdeleteリクエストを送る
  <%= f.submit "Unfollow", class: "btn" %>
<% end %>
一つのテンプレートの中でフォロー一覧、フォロワー一覧を表示する
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

どっちのアクションでも同じテンプレートにrenderし、タイトルや@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 #URLからIDを引っ張ってきて、そのRelationship.followedを探す
    current_user.unfollow(user)
    redirect_to user
  end
FollowボタンAjax

followボタンを押すたびにhtmlの再描画などが発生して重くならないように、javascriptを使って実装してみよう
統計情報、フォローボタンの変更

<%= form_with(model: current_user.active_relationships.build, remote: true) do |f| %>

remote: trueを引数に入れると、javascriptからのリクエストも受け付ける(xmlhttp)

生成されるhtml
<form action="/relationships/117" class="edit_relationship" <span style="color: #2196f3">data-remote="true"</span>
      id="edit_relationship_117" method="post">
def create
    @user = User.find(params[:followed_id])
    current_user.follow(@user)
    respond_to do |format|
      format.html { redirect_to @user } #リクエストがhtmlかjavascriptによってかによって変わる
      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
$("#follow_form").html("<%= escape_javascript(render('users/follow')) %>");
# follow_formというidが割り振られた部分を次の表示に切り替える
$("#followers").html('<%= @user.followers.count %>');
ステータスフィード

自分の投稿と、フォローしている人の投稿を表示する
has_manyでメソッドを生成すると、

@user.following_ids

=
@user.following.map(&:id)

「ids」というIDの集合を取得するメソッドも追加される

Micropost.where("user_id IN <span style="color: #F5A2A2">(?)</span> OR user_id =<span style="color: #00cccc"> ?</span>", <span style="color: #F5A2A2">following_ids</span>,<span style="color: #00cccc"> id</span>)

さらにリファクタリングすると

Micropost.where("user_id IN (:following_ids) OR user_id = :user_id",
    following_ids: following_ids, user_id: id)
#キーワード引数も使える