以下代码执行以下操作:如果用户已投票向他显示删除投票表单和投票表单。如果用户投票,则向他显示投票表单和删除投票表单。否则只显示投票和投票表格(我省略了一些代码,所以问题不会太长)。
(场景:用户投票失败):
posts_controller.rb:
def show
@post = Post.find(params[:id])
@replies = @post.replies.paginate(page: params[:page])
@reply = @post.replies.build
@vote = Vote.new
store_location
end
votes_controller.rb:
class VotesController < ApplicationController
before_filter :signed_in_user
def create
@votable = find_votable
# Destroy the vote first in case the user already voted
if already_voted?
@vote = @votable.votes.find_by_user_id(current_user.id)
@vote.destroy
end
@vote = @votable.votes.build(params[:vote])
@vote.user_id = current_user.id
@votable.save
respond_to do |format|
format.html { redirect_back }
format.js
end
end
def destroy
@votable = find_votable
@vote = @votable.votes.find_by_user_id(current_user.id)
@vote.destroy
@votable.reload
respond_to do |format|
format.html { redirect_back }
format.js
end
end
private
def find_votable
params.each do |name, value|
if name =~ /(.+)_id$/
return $1.classify.constantize.find(value)
end
end
nil
end
def already_voted?
@votable.votes.exists?(:user_id => current_user.id)
end
end
文章/ vote_form
<div class="vote-form">
<% if @post.votes.exists?(:user_id => current_user.id) %>
<% if @post.votes.find_by_user_id(current_user.id).polarity == -1 %>
<%= form_for ([@post, @vote]), remote: true do |f| %>
<%= f.hidden_field :polarity, value: 1 %>
<div class="form-actions">
<%= button_tag type: :submit, class: "btn btn-small vote" do %>
<i class="icon-thumbs-down"></i> Vote up
<% end %>
</div>
<% end %>
<%= form_for ([@post, @post.votes.find_by_user_id(current_user.id)]),
method: :delete,
remote: true do |f| %>
<div class="form-actions">
<%= button_tag type: :submit, class: "btn btn-small btn-primary unvote" do %>
<i class="icon-thumbs-up"></i> Vote down
<% end %>
</div>
<% end %>
<% end %>
票/ create.js:
$('#<%= @votable.class.name.downcase %>-<%= @votable.id %> .vote-form').html(
"<%= escape_javascript(render('shared/delete_vote')) %>"
);
共享/ _delete_vote.html.erb:
<% if @votable.votes.find_by_user_id(current_user.id).polarity == -1 %>
<%= form_for ([@votable, @votable.votes.new]), remote: true do |f| %>
<div class="form-actions">
<%= button_tag type: :submit, class: "vote-down btn btn-small" do %>
<i class="icon-thumbs-up"></i> Vote up
<% end %>
</div>
<% end %>
<%= form_for ([@votable, @vote]), method: :delete, remote: true do |f| %>
<div class="form-actions">
<%= button_tag type: :submit, class: "vote-up btn btn-small btn-primary" do %>
<i class="icon-thumbs-up"></i> Vote down
<% end %>
</div>
<% end %>
<% end %>
所以,现在一切正常,除了我点击投票,然后立即投票(没有刷新页面)时出现此错误:< / p>
ActionView::Template::Error (undefined method `polarity' for nil:NilClass): 1: <% if @votable.votes.find_by_user_id(current_user.id).polarity == 1 %> 2: <%= form_for ([@votable, @vote]), method: :delete, remote: true do |f| %>
可能是什么问题?
修改
我意识到错误消息中的行是问题(不是@votable
):
<% if @votable.votes.find_by_user_id(current_user.id).polarity == 1 %>
奇怪,我认为它与
相同<% if @post.votes.find_by_user_id(current_user.id).polarity == 1 %>
答案 0 :(得分:1)
我认为问题在于:
def destroy
@votable = find_votable
@vote = @votable.votes.find_by_user_id(current_user.id)
@vote.destroy
@votable.reload
respond_to do |format|
format.html { redirect_back }
format.js
end
end
您销毁当前用户的投票,因此无法在视图中找到:
@votable.votes.find_by_user_id(current_user.id).polarity
这就是nil调用极性的原因。你应该改写投票操作的逻辑。
作为最简单的解决方案,您可以替换
if @votable.votes.find_by_user_id(current_user.id).polarity == -1
带
if @votable.votes.find_by_user_id(current_user.id).blank?