Rails 4 ajax выступает в роли голосов с турбо ссылками, подсчет голосов не обновляется
Я могу щелкнуть ссылку один раз, и счетчик обновится, но после этого он не обновится и не обновится в базе данных (глядя на консоль).
index.html.haml
.votes
- if current_user.liked? skit
= link_to unlike_skit_path(skit), method: :get, remote: true, class: "unlike-post" do
.upvote
%span.upvote-link
%i.fa.fa-caret-up
.vote-count= skit.votes_for.size
- else
= link_to like_skit_path(skit), method: :get, remote: true, class: "like-post" do
.upvote
%span.upvote-link
%i.fa.fa-caret-up
.vote-count= skit.votes_for.size
routes.rb
resources :skits do
resources :challenges
member do
get "like", to: "skits#like"
get "unlike", to: "skits#unlike"
end
end
unlike.js.erb
$('.unlike-post').bind('ajax:success', function(){
$(this).find('.vote-count').html('<%= escape_javascript @skit.votes_for.size.to_s %>');
});
like.js.erb
$('.like-post').bind('ajax:success', function(){
$(this).find('.vote-count').html('<%= escape_javascript @skit.votes_for.size.to_s %>');
});
skits_controller.rb
def like
@skit.liked_by current_user
respond_to do |format|
format.html { redirect_to skits_path, notice: 'Successfully voted!' }
format.js { render layout: false }
end
end
def unlike
@skit.unliked_by current_user
respond_to do |format|
format.html { redirect_to skits_path, notice: 'Successfully voted!' }
format.js { render layout: false }
end
end
РЕДАКТИРОВАТЬ
После применения справки снизу не сохраняется в базе данных:
Когда это сохраняется в базе данных:
2 ответа
Проблема здесь заключается в том, что вы используете HTTP-метод для этого запроса, вы используете GET, когда хотите получить информацию с сервера, но если вы хотите обновить ресурсы, GET - неправильный путь.
На вашем месте я бы использовал метод PATCH для этого:
Методы HTTP PATCH могут использоваться для обновления частичных ресурсов. Например, когда вам нужно обновить только одно поле ресурса, PUTting полное представление ресурса может быть громоздким и использовать большую пропускную способность
resources :skits do
resources :challenges
member do
patch :like
patch :unlike
end
end
Обновите method
в твоем хамле:
.votes
- if current_user.liked? skit
= link_to unlike_skit_path(skit), method: :patch, remote: true, class: "unlike-post" do
.upvote
%span.upvote-link
%i.fa.fa-caret-up
.vote-count= skit.votes_for.size
- else
= link_to like_skit_path(skit), method: :patch, remote: true, class: "like-post" do
.upvote
%span.upvote-link
%i.fa.fa-caret-up
.vote-count= skit.votes_for.size
Также убедитесь, что вы обновляете нужный элемент в вашем js.erb
решение для этого будет использовать @skit.id
#app/views/skits/like.js.erb
$("#<%=j @skit.id %>").find(".vote-count").html('<%=j @skit.votes_for.size.to_s %>');
Кстати, вам не нужно использовать ajax:success
, format.js
с этим справлюсь
Добавить в @max
комментарий, вы захотите посмотреть на DRY вверх вашего кода (используя HTTP Verbs
а также actions
соответственно):
# config/routes.rb
resources :skits do
resources :challenges
match :like, via: [:post, :delete], on: :member #-> url.com/skits/:id/like
end
# app/controllers/skits_controller.rb
class SkitsController < ApplicationController
def like
@skit.liked_by current_user if request.post?
@skit.unliked_by current_user if request.delete?
respond_to do |format|
format.html { redirect_to skits_path, notice: 'Successfully voted!' }
format.js #-> format.js doesn't render layout anyway
end
end
end
Вы сможете использовать следующее:
#app/views/skits/index.html.erb
<%= render @skits %>
#app/views/skits/_skit.html.erb
.votes
- method = current_user.liked?(skit) ? :post : :delete
= link_to skit_like_path(skit), method: method, remote: true, id: skit.id do
.upvote
%span.upvote-link
%i.fa.fa-caret-up
.vote-count= skit.votes_for.size
Решение
Что касается проблемы обновления, вы хотите убедиться, что вы обновляете правильный элемент через ваш js.erb
:
#app/views/skits/like.js.erb
$("#<%=j @skit.id %>").find(".vote-count").html('<%=j @skit.votes_for.size.to_s %>');
Вам не нужно привязывать приведенный выше код к ajax:success
- звонит format.js
запустит код в конце запроса. Хотя это может потребовать доработки, оно должно работать.