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) #キーワード引数も使える