簡體   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