繁体   English   中英

使用Ajax和acts_as_votable进行Rails上/下投票

[英]Rails upvote/downvote using Ajax and acts_as_votable

还是对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中弄乱了一些东西。 有人可以告诉我我所缺少的吗?

如果您看一下所提供的代码,则该代码将为字符串内外的内容着色...并且您会在这里注意到以下行:

 $(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" %>');

如果只是为了消除歧义。 (还要检查其他行是否存在类似问题)


好吧,我认为问题是这样。 单击“ ...”后,转到喜欢的动作(顺便说一句,为保持一致性,您可能应该调用“ like”而不是“ 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>

更好的方法...

#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 } %>");

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM