【问题标题】:Rails upvote/downvote using Ajax and acts_as_votableRails 使用 Ajax 和acts_as_votable 支持/反对
【发布时间】:2016-04-17 21:33:41
【问题描述】:

对于 Rails 来说还是相当新的。我使用acts_as_votable gem 来创建upvote 和upvote 按钮,以允许用户对笑话进行upvote/downvote,但我不能让他们从upvote/downvote 更改(反之亦然)并在每次点击时更新计数器而不刷新页面。我尝试遵循其他类似的答案,但没有运气。这是我尝试实现的。

笑话模型

acts_as_votable 

用户模型

acts_as voter

Routes.rb 是

resources :jokes do
member do
  get "like" => "jokes#upvote"
  get "unlike" => "jokes#downvote"
end
end

笑话控制器是

#upvote from user
def upvote
    @joke = Joke.find(params[:id])
    @joke.upvote_from current_user
    respond_to do |format|
        format.html { redirect_to :back }
        format.js { render :layout => false }
    end
end

#downvote from user
def downvote
    @joke = Joke.find(params[:id])
    @joke.downvote_from current_user
    respond_to do |format|
        format.html { redirect_to :back }
        format.js { render :layout => false }
    end
end

我的看法:

<div class="votes">
<%= link_to like_joke_path(@joke), method: :get, remote: true, class:     'like_joke' do %>
    <button type="button" class="btn btn-info" aria-label="Left Align">
        <i class="fa fa-arrow-up"></i>
        <span class="badge vote_count"><%= @joke.get_upvotes.size %></span>
    </button>
<% end %>

<%= link_to unlike_joke_path(@joke), method: :get, remote: true, class: 'unlike_joke' do %>
    <button type="button" class="btn btn-info" aria-label="Left Align">
        <i class="fa fa-arrow-down"></i>
        <span class="badge voute_count"><%= @joke.get_downvotes.size %></span>
    </button>
<% end %>
</div>

like.js.erb:

$('.like_joke').bind('ajax:success', function(){
   $(this).parent().parent().find('.vote_count').html('<%= escape_javascript     @joke.votes_for.size.to_s %>');
   $(this).closest('.like_joke').hide();
   $(this).closest('.votes').html(' <%= link_to "Unlike",  unlike_joke_path(@joke), remote: true, method: :get, class: 'unlike_joke' %>');
});

最后不像.js.erb:

$('.unlike_joke').bind('ajax:success', function(){
   $(this).parent().parent().find('.vote_count').html('<%= escape_javascript @joke.votes_for.size.to_s %>');
   $(this).closest('.unlike_joke').hide();
   $(this).closest('.votes').html(' <%= link_to "Like", like_joke_path(@joke), remote: true, method: :get, class: 'like_joke' %>');
});

这是呈现的 HTML:

<div class="votes">
<a class="like_joke" data-remote="true" data-method="get" href="/jokes/11-cat-joke-title/like">
    <button type="button" class="btn btn-info" aria-label="Left Align">
        <i class="fa fa-arrow-up"></i>
        <span class="badge vote_count">0</span>
    </button>
</a>
<a class="unlike_joke" data-remote="true" data-method="get" href="/jokes/11-cat-joke-title/unlike">
    <button type="button" class="btn btn-info" aria-label="Left Align">
        <i class="fa fa-arrow-down"></i>
        <span class="badge voute_count">1</span>
     </button>
</a></div>

当我查看 js 控制台时,我在 jquery.js?body=1:9665 处收到内部服务器错误,即 xhr.send( ( options.hasContent && options.data ) || null );

看起来我很接近,但我认为我在我的观点和 js 中搞砸了一些东西。有人可以告诉我我缺少什么吗?

【问题讨论】:

    标签: javascript ruby-on-rails ruby ajax acts-as-votable


    【解决方案1】:

    如果您查看您提供的代码...该代码为字符串内部和外部的内容着色...您会在此处注意到这一行:

     $(this).closest('.votes').html(' <%= link_to "Unlike",  unlike_joke_path(@joke), remote: true, method: :get, class: 'unlike_joke' %>');
    

    被着色,以便部分代码在字符串内...但部分不是(向右滚动查看它,它接近尾声)。

    我不确定这是您的错误,但您可能应该考虑将其更改为:

     $(this).closest('.votes').html(' <%= link_to "Unlike",  unlike_joke_path(@joke), remote: true, method: :get, class: "unlike_joke" %>');
    

    如果只是为了消除歧义。 (另请检查其他行是否有类似问题)


    好的,我认为问题是这样的。 一旦你点击了喜欢......你就去喜欢的动作(顺便说一句,你应该叫'喜欢'而不是'upvote'以保持一致性)> 然后你渲染like.js。

    此时您希望 js 实际更新点赞数等。 您已经拥有 javascript,并且只想立即运行它。 你不需要将它绑定到ajax成功......你已经成功了。所以你的 like.js 应该只包含裸 javascript 来实际更新屏幕,例如:

    var like_joke = $('.unlike_joke');
    like_joke.parent().parent().find('.vote_count').html('<%= escape_javascript     @joke.votes_for.size.to_s %>');
    like_joke.closest('.like_joke').hide();
    like_joke.closest('.votes').html(' <%= link_to "Unlike",  unlike_joke_path(@joke), remote: true, method: :get, class: 'unlike_joke' %>');
    

    注意:未经测试,可能存在错误,但你明白了。不要放置一个会在 ajax 成功时被调用的函数,否则它将坐在那里等待其他一些成功的发生。成功已经发生了……现在就去做吧:)

    另请注意:这里有一个错字:

       <span class="badge voute_count"><%= @joke.get_downvotes.size %></span>
    

    应该是

       <span class="badge vote_count"><%= @joke.get_downvotes.size %></span>
    

    【讨论】:

    • 谢谢!我已经添加了渲染的 HTML 以及我从 js 控制台得到的错误,以及它被绊倒的代码行。
    • @GregSéguin 好的,更新了我认为可能发生的事情。试试看。
    【解决方案2】:

    更好的方法...

    #config/routes.rb
    resources :jokes do
      match :vote, via: [:post, :delete], on: :member
    end
    
    #app/controllers/jokes_controller.rb
    class JokesController < ApplicationController
       def vote
           @joke = Joke.find(params[:id])
           if request.post?
               @joke.upvote_from current_user
           elsif request.delete?
               @joke.downvote_from current_user
           end
           respond_to do |format|
              format.html { redirect_to :back }
              format.js
           end
       end
    end
    

    创建一个partial 视图:

    #app/views/jokes/_vote.html.erb
    <% voted   = current_user.voted_for? joke %>
    <% styling = voted ? "" : "un" %>
    <% arrow   = voted ? "up" : "down" %>
    <% method  = voted ? :delete : :post %>
    
    <%= link_to vote_joke_path(joke), method: method, remote: true, class: '#{styling}like_joke', id: joke.id do %>
        <button type="button" class="btn btn-info" aria-label="Left Align">
            <i class="fa fa-arrow-<%= arrow %>"></i>
            <span class="badge vote_count"><%= joke.get_upvotes.size %></span>
        </button>
    <% end %>
    
    #app/views/jokes/show.html.erb
    <%= render partial: "vote", locals: { joke: @joke } %>
    

    这样,当您从 JokesController 调用 vote.js.erb 时,您将能够使用以下内容:

    #app/views/jokes/vote.js.erb
    $("<%=j @joke.id %>").html("<%=j render partial: "jokes/vote", locals: { joke: @joke } %>");
    

    【讨论】:

    • 这可能行得通 - 但 OP 正在尝试学习如何做到这一点,并且会更好地找出他们尝试的问题出了什么问题,而不是作为既成事实提供解决方案
    • 如果OP不喜欢我会删除它
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-16
    • 2016-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-02
    • 2013-08-05
    相关资源
    最近更新 更多