【问题标题】:Rails 4 ajax acts as votable with turbo links vote counts not updatingRails 4 ajax 充当可投票者,涡轮链接投票计数未更新
【发布时间】:2016-01-27 07:00:43
【问题描述】:

我可以点击一次链接,计数会更新,但之后点击不会更新,也不会更新到数据库中(查看控制台)。

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

编辑

从底部应用帮助后,不保存到数据库中:

存入数据库时​​:

【问题讨论】:

  • 不要使用GET 请求来创建或销毁资源。 GET 请求保存在浏览器历史记录中。而是使用 POST /skits/1/likes 之类的东西来创建一个喜欢和 DELETE /likes/:id 来不喜欢。
  • @max 谢谢你,你认为你可以发布一个例子吗?另外,用 PUT 代替呢?
  • 你可以使用PUT,但它不是很RESTful。而PUT /skits/1/like 更像是一个过程。我今天没有时间输入完整的答案,对不起。然而,这是一个非常常见的场景,你应该能够在网上找到很多例子。

标签: jquery ruby-on-rails ajax ruby-on-rails-4 acts-as-votable


【解决方案1】:

要添加到@max 的评论,您需要查看DRY 修改您的代码(相应地使用您的HTTP Verbsactions):

# 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 将在请求结束时运行代码。虽然这可能需要调整,但它应该可以工作。

【讨论】:

  • 我不得不把.html('&lt;%=j改成.html('&lt;%=escape_javascript,还把id里的j去掉了。但是,我不再将其保存到数据库中了吗?
  • 我添加了显示 SQL 的控制台屏幕截图
  • 查看您的SQL 日志,它似乎正在向适当的命令等发送所需的请求。您确定它没有更新数据库吗?
  • 当它保存到他的数据库中时,我已经上传了一个新的 SQL 屏幕截图。在 COMMIT 之前有一个 DELETE SQL...实际上之前的屏幕截图是错误的。我有一个实际的,它没有显示对数据库的更新。让我知道它是否也应该是这样的
【解决方案2】:

这里的问题是您用于此请求的 HTTP 方法,当您想从服务器获取信息时使用 GET,但如果您想更新资源,则 GET 不是正确的方法。

如果我是你,我会为此使用 PATCH 方法:

HTTP 方法 PATCH 可用于更新部分资源。为了 例如,当您只需要更新资源的一个字段时, 放置一个完整的资源表示可能很麻烦,而且 使用更多带宽

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

更新你的haml中的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:successformat.js 会为你处理这个问题

【讨论】:

  • 我是否需要将链接按钮上的类或其他内容从like-post 更改为like-post,反之亦然?因为这在第一次点击时有效,但在那之后,它就不再更新了
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多