LoginSignup
1
2

More than 3 years have passed since last update.

【rails】Ajaxを使ったフォローボタンの実装で躓いたところ

Posted at

はじめに

初学者がポートフォリオ作成の際に躓いたことをメモします。
今回は躓いた部分だけ記載します。全体を知りたい方は下記のリンクがわかりやすいです。
https://railstutorial.jp/chapters/following_users?version=4.2#sec-a_working_follow_button_the_standard_way
https://qiita.com/Kaisyou/items/e918b77465e3f55c97a2

Ajaxとは

『Ajaxとは、あるWebページを表示した状態のまま、別のページや再読込などを伴わずにWebサーバ側と通信を行い、動的に表示内容を変更する手法。ページ上でプログラムを実行できるプログラミング言語JavaScriptの拡張機能を用いる。』

簡単に言うと、『javascriptによって必要な部分だけを更新する技術。その為ページ全体を再読み込みする必要がなく、素早いレスポンスが可能になる』と言ったところでしょうか?

前提

今回はユーザー一覧画面(users/index)でフォローボタンを表示します。

users_controller.rb
def index
    @q = User.ransack(params[:q])
    @users = @q.result(distinct: true)
  end
users/index.slim
- @users.each do |user| 
# (中略)
  == render "follow_form" , object: @user if logged_in?
users/_follow_form.slim
- unless current_user?(object) 
  div id="follow_form_#{object.id}"  #フォロー一覧画面でボタンを表示させる際にuserを区別する為に動的にしている
    - if current_user.following?(object) 
      = render 'unfollow' , object: object
    - else 
      = render 'follow' , object: object
users/_follow.slim
= form_with(model: current_user.active_relationships.build) do |f| 
 = hidden_field_tag :followed_id, object.id 
 = f.submit "Follow", class: "btn btn-primary" 

躓いたところ(1) relationships_controller.rb内のrespond_toについて

他の記事を見るとrespond_toを使っている場合が多かったが内容が理解出来なかった。
respond_toについて以下のリンクがわかりやすかった。
https://www.javadrive.jp/rails/controller/index7.html#section3

送られてくるリクエストの形式によって処理を分ける。リクエストがHTML形式で送られてきた場合とjs形式で送られてきた場合で処理を分けている。

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



しかし今回はform_withでremote:trueを設定している為、HTML形式でリクエストが送られることはないので以下のようにした。

relationships_controller.rb
class RelationshipsController < ApplicationController
before_action :logged_in_user

  def create
    @user = User.find(params[:followed_id])
    current_user.follow(@user)
  end

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

end

remote:trueを設定している為、JS形式のリクエストが送られる。デフォルトでアクション名と同じ名前のjsファイルが呼ばれる。
( createアクションの場合: app/views/relationships/create.js.erb )


躓いたところ(2) create.js.erb内の"#follow_form_<%= @user.id %>

JQueryのコードの理解が足りずバグが発生した。users/show画面では#follow_formで良いが、ユーザー 一覧画面の場合ユーザー を区別しなければならない為、idを動的に変更する必要がある。

views/relationships/create.js.erb
$("#follow_form_<%= @user.id %>").html("<%= j(render 'users/unfollow', object: @user) %>"); 
$("#followers").html('<%= @user.followers.count %>');  #ユーザー一覧画面では使わない(フォロワーの数を表示しない為)

上記のコードはJQueryで書かれており、htmlメソッドは指定した要素を書き換えることができる。

htmlメソッドについて https://www.sejuku.net/blog/38267

一行目でusers/showの#follow_form<%= @user.id %>の内容をusers/unfollowに置き換えている。また@userusers/unfollow内でobjectとして参照している。

最後に

誰かのお役にたてれば幸いです。
間違えている部分があればコメントお願いいたします。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2