質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.35%

  • Ruby

    10208questions

    Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

  • Ruby on Rails

    9551questions

    Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

  • Ajax

    1407questions

    Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

Ruby on RailsでAjaxを利用して非同期で部分テンプレートのデータを変更する方法

受付中

回答 0

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 454

ruby_egg

score 19

Ruby on RailsでAjaxを利用して非同期で部分テンプレートのデータを変更したいと考えております。
リロードすると変更されるのですが、部分テンプレートのボタンをクリックしただけでは、Ajaxが正しく動きません。
アドバイスなどしていただけますと幸いです。よろしくお願いいたします。
コードやデータベース設計は以下の通りです。

# ユーザーのモデルです
User.rb
# ユーザーが作成したチームです
has_many :created_teams, class_name: “Team”, foreign_key: "owner_id", dependent: :destroy
# ユーザーが参加したチームです
has_many :participated_teams, through: :user_teams, source: :team
# ユーザーとチームの中間テーブルのモデルです
has_many :user_teams

#「1つのチームには1回しか参加できない」というルール
def participatable_for?(team)
  team && !user_teams.exists?(team_id: team.id)
end

# 現在のユーザーがチームに参加していたらtrueを返す
def participating?(team)
  participated_teams.include?(team)
end
# チームのモデルです
Team.rb
# チームを作成したユーザーです
belongs_to :owner, class_name: "User"
# チームに参加したユーザーです
has_many :participants, through: :user_teams, source: :user
# ユーザーとチームの中間テーブルのモデルです
has_many :user_teams
# ユーザーとチームの中間テーブルのモデルです
user_team.rb
belongs_to :user
belongs_to :team
# チームのコントローラーです
TeamsController.rb

def index
  @teams = Team.order(created_at: :desc)
end

def show
  @team = Team.find(params[:id])
end

def edit
  省略
end

def update
  省略
end

def create
  省略
end

def new
  省略
end

def destroy
  省略
end

# ユーザーをチームに参加させるアクションです
def participate
  @team = Team.find(params[:id])
  current_user.participated_teams << @team
  respond_to do |format|
    format.html
    format.js
  end
end

# ユーザーをチームから退会させるアクションです
def unparticipate
  @team = Team.find(params[:id])
  current_user.participated_teams.destroy(Team.find(params[:id]))
  respond_to do |format|
    format.html
    format.js
  end
end

private

# ストロングパラメーター
def team_params
   params.require(:team).permit(:name)
end
teams/index.html.slim
h2 チーム一覧
.team-contents
  - if @teams.present?
    - @teams.each do |team|
      article.team
        h2 = team.name
        .team-footer
          .team-detail
           # この部分テンプレートが以下のファイルです。
            == render "participates", team: team
            = link_to "詳細を見る", team, class: "more
  - else
    p チームがありません。

ユーザーはグループに参加することが出来ます。退会することも出来ます。
以下の部分テンプレートのボタンをAjaxで切り替えて更新するのが目的です。
ボタンの動きはユーザーがチームに参加してる場合は「退会する」、参加していない場合は「参加する」ボタンを切り替えて表示するというものです。

teams/_participates.html.slim
#team-btn
  - if current_user && current_user.participatable_for?(team)
   = link_to "参加する", [:participate, team], method: :patch, class: "more", remote: true
  - if current_user && current_user.participating?(team)
   = link_to "退会する", [:unparticipate, team], method: :patch, class: "more", remote: true
Team/participate.js.html
$(“#team-btn”).html("<%= j(renderteams/participates') %>");
config/application.rb

# 以下を追記
config.action_view.embed_authenticity_token_in_remote_forms = true
config/routes.rb

resources :users
resources :teams do
  member do
    patch "participate", "unparticipate"
  end
end

部分テンプレートの「参加する」「退会する」というボタンを押すとAjaxで非同期でボタンを切り替えるのが目的です。
しかし、ボタンを押した後にブラウザをリロードしないとボタンが切り替わりません。

Turbolinksはオフにしています。
バージョンは以下の通りです。

Ruby: 2.3.1
Rails: 5.0.2

アドバイスなどよろしくお願いいたします。

<追記>
以下のように再実装したところチームの詳細ページ(show)では上手くAjaxで動くようになりました。
が、しかし上記に書いているチームの一覧ページ(index)では上手く動きません。なぜでしょうか?

teams/index.html.slim
h2 チーム一覧
.team-contents
  - if @teams.present?
    - @teams.each do |team|
      article.team
        h2 = team.name
        .team-footer
          .team-detail
           # この部分テンプレートが以下のファイルです。
            #team-btn
              - if current_user && current_user.participatable_for?(team)
                == render "participates", team: team
              - if current_user && !team.created_by?(current_user) && current_user.participating?(team)
                == render "unparticipates", team: team
            = link_to "詳細を見る", team, class: "more
  - else
    p チームがありません。
#teams/_participates.html.slim

= link_to "参加する", [:participate, team], method: :patch, class: "more", remote: true
#teams/_unparticipates.html.slim

= link_to "退会する", [:unparticipate, team], method: :patch, class: "more", remote: true
#teams/participate.js.erb

$("#team-btn").html("<%= escape_javascript render :partial => "teams/unparticipates" ,locals: {team: @team} %>");
#teams/unparticipate.js.erb

$("#team-btn").html("<%= escape_javascript render :partial => "teams/participates" ,locals: {team: @team} %>");

上記のように実装しました所、以下のshowページでは上手くAjaxが動きました。

teams/show.html.slim
h2 チーム詳細ページ
.team-contents
  h2 = @team.name
  # この部分が部分テンプレートです。
    #team-btn
    - if current_user && current_user.participatable_for?(team)
      == render "participates", team: @team
    - if current_user && current_user.participating?(team)
      == render "unparticipates", team: @team

しかし、上記のteams/index.html.slimでは正しく動きません。
何か、アドバイスなどございましたら、よろしくお願いいたします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正の依頼

  • kei344

    2017/11/02 11:09

    https://teratail.com/questions/98840 この質問と内容が同じです。teratailは質問内容の編集ができるので、変更がある場合は新しい質問をするのではなく編集してください。また、どちらかを削除されるよう運営に連絡されることをお勧めします。https://teratail.com/contact/input

    キャンセル

まだ回答がついていません

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.35%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Ruby

    10208questions

    Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

  • Ruby on Rails

    9551questions

    Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

  • Ajax

    1407questions

    Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。