Ruby on RailsでAjaxを利用して非同期で部分テンプレートのデータを変更したいと考えております。
リロードすると変更されるのですが、部分テンプレートのボタンをクリックしただけでは、Ajaxが正しく動きません。
アドバイスなどしていただけますと幸いです。よろしくお願いいたします。
コードやデータベース設計は以下の通りです。
Ruby
1# ユーザーのモデルです 2User.rb 3# ユーザーが作成したチームです 4has_many :created_teams, class_name: “Team”, foreign_key: "owner_id", dependent: :destroy 5# ユーザーが参加したチームです 6has_many :participated_teams, through: :user_teams, source: :team 7# ユーザーとチームの中間テーブルのモデルです 8has_many :user_teams 9 10#「1つのチームには1回しか参加できない」というルール 11def participatable_for?(team) 12 team && !user_teams.exists?(team_id: team.id) 13end 14 15# 現在のユーザーがチームに参加していたらtrueを返す 16def participating?(team) 17 participated_teams.include?(team) 18end
Ruby
1# チームのモデルです 2Team.rb 3# チームを作成したユーザーです 4belongs_to :owner, class_name: "User" 5# チームに参加したユーザーです 6has_many :participants, through: :user_teams, source: :user 7# ユーザーとチームの中間テーブルのモデルです 8has_many :user_teams
Ruby
1# ユーザーとチームの中間テーブルのモデルです 2user_team.rb 3belongs_to :user 4belongs_to :team
Ruby
1# チームのコントローラーです 2TeamsController.rb 3 4def index 5 @teams = Team.order(created_at: :desc) 6end 7 8def show 9 @team = Team.find(params[:id]) 10end 11 12def edit 13 省略 14end 15 16def update 17 省略 18end 19 20def create 21 省略 22end 23 24def new 25 省略 26end 27 28def destroy 29 省略 30end 31 32# ユーザーをチームに参加させるアクションです 33def participate 34 @team = Team.find(params[:id]) 35 current_user.participated_teams << @team 36 respond_to do |format| 37 format.html 38 format.js 39 end 40end 41 42# ユーザーをチームから退会させるアクションです 43def unparticipate 44 @team = Team.find(params[:id]) 45 current_user.participated_teams.destroy(Team.find(params[:id])) 46 respond_to do |format| 47 format.html 48 format.js 49 end 50end 51 52private 53 54# ストロングパラメーター 55def team_params 56 params.require(:team).permit(:name) 57end
HTML
1teams/index.html.slim 2h2 チーム一覧 3.team-contents 4 - if @teams.present? 5 - @teams.each do |team| 6 article.team 7 h2 = team.name 8 .team-footer 9 .team-detail 10 # この部分テンプレートが以下のファイルです。 11 == render "participates", team: team 12 = link_to "詳細を見る", team, class: "more” 13 - else 14 p チームがありません。
ユーザーはグループに参加することが出来ます。退会することも出来ます。
以下の部分テンプレートのボタンをAjaxで切り替えて更新するのが目的です。
ボタンの動きはユーザーがチームに参加してる場合は「退会する」、参加していない場合は「参加する」ボタンを切り替えて表示するというものです。
HTML
1teams/_participates.html.slim 2#team-btn 3 - if current_user && current_user.participatable_for?(team) 4 = link_to "参加する", [:participate, team], method: :patch, class: "more", remote: true 5 - if current_user && current_user.participating?(team) 6 = link_to "退会する", [:unparticipate, team], method: :patch, class: "more", remote: true
HTML
1Team/participate.js.html 2$(“#team-btn”).html("<%= j(render ‘teams/participates') %>");
Ruby
1config/application.rb 2 3# 以下を追記 4config.action_view.embed_authenticity_token_in_remote_forms = true
Ruby
1config/routes.rb 2 3resources :users 4resources :teams do 5 member do 6 patch "participate", "unparticipate" 7 end 8end
部分テンプレートの「参加する」「退会する」というボタンを押すとAjaxで非同期でボタンを切り替えるのが目的です。
しかし、ボタンを押した後にブラウザをリロードしないとボタンが切り替わりません。
Turbolinksはオフにしています。
バージョンは以下の通りです。
Ruby: 2.3.1 Rails: 5.0.2
アドバイスなどよろしくお願いいたします。
<追記>
以下のように再実装したところチームの詳細ページ(show)では上手くAjaxで動くようになりました。
が、しかし上記に書いているチームの一覧ページ(index)では上手く動きません。なぜでしょうか?
HTML
1teams/index.html.slim 2h2 チーム一覧 3.team-contents 4 - if @teams.present? 5 - @teams.each do |team| 6 article.team 7 h2 = team.name 8 .team-footer 9 .team-detail 10 # この部分テンプレートが以下のファイルです。 11 #team-btn 12 - if current_user && current_user.participatable_for?(team) 13 == render "participates", team: team 14 - if current_user && !team.created_by?(current_user) && current_user.participating?(team) 15 == render "unparticipates", team: team 16 = link_to "詳細を見る", team, class: "more” 17 - else 18 p チームがありません。
Ruby
1#teams/_participates.html.slim 2 3= link_to "参加する", [:participate, team], method: :patch, class: "more", remote: true
Ruby
1#teams/_unparticipates.html.slim 2 3= link_to "退会する", [:unparticipate, team], method: :patch, class: "more", remote: true
Ruby
1#teams/participate.js.erb 2 3$("#team-btn").html("<%= escape_javascript render :partial => "teams/unparticipates" ,locals: {team: @team} %>");
Ruby
1#teams/unparticipate.js.erb 2 3$("#team-btn").html("<%= escape_javascript render :partial => "teams/participates" ,locals: {team: @team} %>");
上記のように実装しました所、以下のshowページでは上手くAjaxが動きました。
HTML
1teams/show.html.slim 2h2 チーム詳細ページ 3.team-contents 4 h2 = @team.name 5 # この部分が部分テンプレートです。 6 #team-btn 7 - if current_user && current_user.participatable_for?(team) 8 == render "participates", team: @team 9 - if current_user && current_user.participating?(team) 10 == render "unparticipates", team: @team
しかし、上記のteams/index.html.slimでは正しく動きません。
何か、アドバイスなどございましたら、よろしくお願いいたします。
あなたの回答
tips
プレビュー