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

в отличие от.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

РЕДАКТИРОВАТЬ

После применения справки снизу не сохраняет в БД:

введите здесь описание изображения

Когда он сохраняется в базе данных:

введите здесь описание изображения


person hellomello    schedule 27.01.2016    source источник
comment
Не используйте запрос GET для создания или уничтожения ресурса. GET-запросы сохраняются в истории браузера. Вместо этого используйте что-то вроде POST /skits/1/likes для создания лайка и DELETE /likes/:id для непохожести.   -  person max    schedule 27.01.2016
comment
@max, спасибо, как вы думаете, вы можете опубликовать пример? Кроме того, как насчет PUT вместо этого?   -  person hellomello    schedule 27.01.2016
comment
Вы можете использовать PUT, но это не очень RESTful. Скорее PUT /skits/1/like больше похоже на процедуру. У меня нет времени сегодня, чтобы напечатать полный ответ, извините. Однако это чрезвычайно распространенный сценарий, и вы сможете найти немало примеров в Интернете.   -  person max    schedule 27.01.2016


Ответы (2)


Чтобы добавить к комментарию @max, вам нужно посмотреть на ПРОСУШИВАНИЕ вашего кода. (используя ваши 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 запустит код в конце запроса. Хотя это может потребовать настройки, оно должно работать.

person Richard Peck    schedule 27.01.2016
comment
Мне пришлось изменить .html('<%=j на .html('<%=escape_javascript, а также убрать j в идентификаторе. Однако я больше не сохраняю его в базе данных? - person hellomello; 27.01.2016
comment
Я добавил скриншот моей консоли, показывающий SQL - person hellomello; 27.01.2016
comment
Глядя на ваш журнал SQL, кажется, что он отправляет требуемый запрос соответствующим командам и т. Д. Вы уверены, что он не обновляет базу данных? - person Richard Peck; 27.01.2016
comment
Я загрузил новый снимок экрана SQL, когда он сохраняется в базе данных. Перед COMMIT есть DELETE SQL... на самом деле предыдущий снимок экрана был неправильным. У меня есть реальный, который не показывает обновление базы данных. Дайте мне знать, если это должно быть так же - person hellomello; 27.01.2016
comment
Итак, я переключил :post : :delete на :delete : :post, и теперь он обновляется в базе данных, но работает только один раз, он не обновляется несколько раз. - person hellomello; 27.01.2016

Проблема здесь заключается в методе HTTP, который вы используете для этого запроса, вы используете GET, когда хотите получить информацию с сервера, но если вы хотите обновить ресурсы, GET не является правильным способом.

Если бы я был вами, я бы использовал для этого метод PATCH:

HTTP-методы PATCH можно использовать для обновления частичных ресурсов. Например, когда вам нужно обновить только одно поле ресурса, размещение полного представления ресурса может быть громоздким и использовать больше пропускной способности.

resources :skits do
  resources :challenges
  member do 
    patch :like
    patch :unlike
  end
end

Обновите method в вашем haml:

.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 сделает это за вас

person svelandiag    schedule 27.01.2016
comment
Нужно ли мне изменить класс кнопки ссылки или что-то в этом роде с непохожего поста на лайкающего поста и наоборот? Потому что это работает при первом нажатии, но после этого больше не обновляется. - person hellomello; 27.01.2016