この記事は学習した内容をアウトプットし、更に理解を深めるための記録用投稿になります。
投稿している内容と同じ箇所で躓いている方に少しでもお力添えできれば幸いです。
非同期通信の実装をするに至った経緯はポートフォリオを制作後にメンターの方にレビューをいただきました。その際に今後のチャレンジという項目でご指摘をいただいたのでチャレンジしてみました!
わかりやすく説明をしていただいてる方にはほんと感謝です、、、
非同期通信とは
・WEBブラウザからWEBサーバー間のリクエストしてレスポンスが行われるまでに次の処理をする事が可能。
・リクエスト後画面遷移せずにデータの更新が行われる(いいね数が増えるなど)
前提条件
・gem 'jquery-rails'は導入済
・いいね機能実装済み
・料理の内容を投稿するアプリになるのでユーザー(user)、料理(dish)とします
手順
① Ajax処理をするための記述を追加する(remote :true)
② ビューでのいいねボタンを部分テンプレートにするためにファイルを作成(_favorite.html.erb)
③ 部分テンプレートを使いたい箇所に記述する
④ 部分テンプレートにidを持たせる記述をする
⑤ favoriteコントローラのcreate,destroyのリダイレクト先の記述を消す
⑥ view/favoritesにjavascriptに対応するファイルcreate.js.erb、destroy.js.erbを新規作成。
⑦ ⑤でリダイレクト先を消したので④で持たせたidの箇所の更新が行われるようにする記述をする。
解説
① Ajax処理をするための記述を追加する(remote :true)
リンクにこの記述をすることでAjaxに対応できるようになる。
*/views/dishes/show.html.erb
<% if @dish.favorited_by?(current_user) %>
<p class="h4 mt-1 text-center">
<%= link_to dish_favorites_path(@dish.id), method: :delete, remote:true do %>
<i class="fa-solid fa-heart faa-wrench animated-hover" style="color: #ff6347;"></i>
<%= @dish.favorits.count %>
<% end %>
</p>
<% else %>
<p class="h4 mt-1 text-center">
<%= link_to dish_favorites_path(@dish.id), method: :post, remote:true do %>
<i class="fa-regular fa-heart faa-wrench animated-hover" style="color: #ff6347;"></i> <%= @dish.favorits.count %>
<% end %>
</p>
<% end %>
② ビューでのいいねボタンを部分テンプレートにするためにファイルを作成(_favorite.html.erb)
部分テンプレートの記述では@(インスタンス変数)を使用しない。
*/views/dishes/_favorite.html.erb
<% if dish.favorited_by?(current_user) %>
<p class="h4 mt-1 text-center">
<%= link_to dish_favorites_path(dish.id), method: :delete, remote:true do %>
<i class="fa-solid fa-heart faa-wrench animated-hover" style="color: #ff6347;"></i>
<%= dish.favorits.count %>
<% end %>
</p>
<% else %>
<p class="h4 mt-1 text-center">
<%= link_to dish_favorites_path(dish.id), method: :post, remote:true do %>
<i class="fa-regular fa-heart faa-wrench animated-hover" style="color: #ff6347;"></i> <%= dish.favorits.count %>
<% end %>
</p>
<% end %>
③ 部分テンプレートを使いたい箇所に記述する
*/views/dishes/show.html.erb
<%= render 'dishes/favorite', dish: @dish %>
<!--/view/dishes/favorite(_favorite.html.erb)を指定して部分テンプレート内のdishは@dishとする。-->
④ 部分テンプレートにidを持たせる記述をする
以下の記述で[favorite_btn_(dishのid)]とすることができる。
*/views/dishes/show.html.erb
<div id="favorite_btn_<%= @dish.id %>">
<%= render 'dishes/favorite', dish: @dish %>
</div>
⑤ favoriteコントローラのcreate,destroyのリダイレクト先の記述を消す。
*/controllers/favorites_controller.rb
def create
@dish = Dish.find(params[:dish_id])
favorite = current_user.favorits.new(dish_id: @dish.id)
favorite.save
@dish.create_notification_favorite!(current_user)
# redirect_to dish_path(dish.id) <=ここを削除!
end
def destroy
@dish = Dish.find(params[:dish_id])
favorite = current_user.favorits.find_by(dish_id: @dish.id)
favorite.destroy
# redirect_to dish_path(dish.id)<=ここを削除!
end
⑥ view/favoritesにjavascriptに対応するファイルcreate.js.erb、destroy.js.erbを新規作成。
/view/favorites/create.js.erb
/view/favorites/destory.js.erb
⑦ ⑤でリダイレクト先を消したので④で持たせたidの箇所の更新が行われるようにする記述をする。
以下のファイルを記述することでリダイレクト先がなくても[favorite_btn_id]が更新される。
*/views/favorites/create.js.erb
$('#favorite_btn_<%= @dish.id %>').html("<%= j(render partial: 'dishes/favorite', locals: {dish: @dish}) %>");
*/views/favorites/destroy.js.erb
$('#favorite_btn_<%= @dish.id %>').html("<%= j(render partial: 'dishes/favorite', locals: {dish: @dish}) %>");
以上です
⑥の工程でファイルを作る際に/view/favorites/create.js.erbのところを/view/dishes/create.js.erb
としており、コンソールで以下のエラーが出ていました。
No template found for FavoritesController#create, rendering head :no_content
翻訳:FavoritesController#create のテンプレートが見つからず、head :no_content をレンダリング中
/favorites_controller.rbからリダイレクト先を削除したことにより次の目的地として/view/favorites/create.js.erbを読み取らないといけないのにも関わらず/view/dishes/create.js.erbとしていたことでコントローラがどこにいけばわからない状態でした。/view/dishes/create.js.erbを/view/favorites/create.js.erbに変更することでエラーは解消されました。
データの流れを理解できたことにより解決することができたエラーでした。
今後はコメント機能にも非同期通信が使えるみたいなのでさらに実装してみたいと思います!
説明などで間違えている箇所などありましたらご指摘いただけますと幸いです。
よろしくお願いします。