2016-01-13 38 views
1

Rails還是比較新的。我使用acts_as_votable gem來創建upvote和upvote按鈕,以允許用戶upvote/downvote笑話,但我不能讓他們從upvote/downvote(反之亦然)更改,並在每次點擊時更新計數器而不刷新頁面。我嘗試了其他類似的答案,但沒有運氣。這是我試圖實現的。Rails upvote/downvote使用Ajax和acts_as_votable

笑話模型

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

終於unlike.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)||空值 );

看起來我很接近,但我認爲我在我的觀點和js中搞砸了一些東西。有人能告訴我我錯過了什麼嗎?

回答

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成功......你已經成功了。所以你喜歡。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' %>'); 

注:未經測試,可能會有錯誤,但你的想法。不要把一個函數調用成功,否則它會坐在那裏等待一些其他的成功發生。成功已經發生了......現在只是去和做的事:)

另外請注意:這裏有一個錯字:

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

應該

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

謝謝!我已經添加了呈現的HTML以及我從js控制檯獲得的錯誤,以及它被絆倒的代碼行。 –

+0

@GregSéguin確定,更新了我認爲可能會發生的事情。有一個去與看看。 –

0

更好的辦法?

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

這可能很好 - 但是OP正在嘗試學習如何做到這一點,並將更好地爲弄清楚他們所嘗試的是什麼出問題而不是提供解決方案作爲既成事實而更好地服務 –

+0

如果OP不喜歡它 –