Closed fukasawamoe closed 10 months ago
format.jsはRails7系のデフォルトでは使えないのでturbo_streamを使った方が良いかなと思います。
スクリーンショット等を使用して画面のどのボタンを押したら、どこのコントローラーのどのアクションで処理をして非同期処理をしたいのか教えてください
コメントありがとうございます。 承知しました。
現状は、週のボタンを押下するとsteps_controllerのupdate_multipleに飛び、 stepのidから紐づいたachievementのday_check(*配列型 月-日の数値が入り、sizeメソッドで要素の数を数えて週に行った回数をカウントする)に登録していく流れです(すでに配列にある曜日が選択された場合は配列から削除を行う)
以下、ボタン押下後にachievementが非同期通信されない様子
そのため、steps_controllerのadd_day_checkの@.step.achievement.save!の下あたりにどうにか上手く書けないかと考えています。 ちなみに、週のボタンの処理に関しましてはすでにTurboStreamを使用しており、goals/show.html.erbにて、<%= turbo_frame_tag step do %>を組み込み非同期通信にしています。(Achievementのグラフにも適用しようとしたのですがこちらの場合は変化なしで更新されませんでした)
現在はturbo_streamで実装し直そうとしており、Achievementモデルが更新される際にhome/_achievement.html.erbをレンダリングするようにしたいと考えています。
#Achievement.rb
class Achievement < ApplicationRecord
belongs_to :step
def broadcast_achievement(current_user)
broadcast_replace_to("achievements", partial: "home/achievement", locals: { steps: Step.where(user_id: current_user.id) })
end
end
#steps_controllerより一部抜粋
class StepsController < ApplicationController
def add_day_check
@step = Step.find_by(id: params[:id], user_id: current_user.id)
if @step && @step.achievement
target_day = params[:day].to_i # この値はリクエストのパラメータから取得
array_day_check = @step.achievement.day_check
if array_day_check.include?(target_day)
array_day_check.delete(target_day)
else
array_day_check<<target_day
end
@step.achievement.save!
@step.achievement.broadcast_achievement(current_user)
redirect_to home_index_path
end
end
end
broadcast使わないで良いと思いますよ 下記記事のイメージでコントローラーに対応するadd_day_check.turbo_stream.erbファイルを作ってあげてそこでHTMLを置き換える処理を書いてあげる感じです(redirect_toも消します)
ありがとうございます! ご提示いただいた内容で実装してみましたところ実装できました。 ~~ですが、グラフの挙動は正しく動くのですが ボタンの連動がうまくいっておらず、おかしな挙動をしてしまいます。~~
説明が難しいので以下にgifを貼りますのでご確認いただければ幸いです。
問題解決のために行ったこと 修正前の<%= turbo_frame_tag step do %>を使用していた際にも同じような事象が起きましたが、 その時はdivタグの前に設置することでこれを回避することができていました。 (そのため以下のコードでも
すみません、以下のようにすることで解決しました...! ご確認よろしくお願いいたします!
<div id="achievement_button">
<% steps.each do |step| %>
<% action = step.action %>
<% times_set = step.times_set %>
<% unless action.blank? && times_set.blank? %>
<li><i class="fa-solid fa-fire" style="color: #f26845;"></i> <%= action %>を週<%= times_set %>回行う</li>
<div class='flex flex-wrap'>
<% (0..6).each do |day| %>
<% if step.achievement.day_check.include?(day) %>
<%= render "achievements/on_button", day: day, step: step %>
<% else %>
<%= render "achievements/off_button", day: day, step: step %>
<% end %>
<% end %>
</div>
<% all_blank = false %>
<% end %>
<% end %>
<%= turbo_stream.update "achievement_button" do %>
<% @steps.each do |step| %>
<% action = step.action %>
<% times_set = step.times_set %>
<% unless action.blank? && times_set.blank? %>
<li><i class="fa-solid fa-fire" style="color: #f26845;"></i> <%= action %>を週<%= times_set %>回行う</li>
<div class='flex flex-wrap'>
<% (0..6).each do |day| %>
<% if step.achievement.day_check.include?(day) %>
<%= render "achievements/on_button", day: day, step: step %>
<% else %>
<%= render "achievements/off_button", day: day, step: step %>
<% end %>
<% end %>
</div>
<% all_blank = false %>
<% end %>
<% end %>
<% end %>
<%= turbo_stream.update "achievement_graph" do %>
<% @steps.each do |step| %>
<div class="grid grid-cols-3 gap-10">
<% if step.action.present?%>
<div id="achievement-<%= step.id %>" class="achievement">
<p><%= step.action %></p>
<% calculated_value1 = (((step.achievement.day_check.size*0.1)/(step.times_set*0.1))* 100).round %>
<div class="radial-progress bg-red-100 text-primary-content border-4 border-primary" style="--value:<%= calculated_value1 %>; --size:12rem; --thickness: 2rem;" role="progressbar"><%= calculated_value1 %>%</div>
</div>
<% end %>
</div>
<% end %>
<% end %>
ajax化がわからないのでご助言いただけると幸いです。 ajax化実現のためにやったこと 各ボタンにremote: trueを表記、idを設定
+app/javascript/custom/steps.js
+/app/views/steps/add_day_check.js.erb
steps_controller.rb