[英]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.