第一篇StackOverFlow帖子,请耐心等待:):
所以我有一个Post模型,它有一个与投票模型的多态关联。
我的主要问题是按最高票数订购每个帖子。我正在尝试实施Upvote系统。问题:如何通过最高投票订购? (@total)
似乎我的视图(@ upcount,@ downcount,@ total)中的代码可能在我的控制器中可能有,但我不知道如何做到这一点。
理想情况下,我想在社区行动中做类似的事情:Post.order(“@ total”),但显然这不起作用。
发布模型
class Post < ActiveRecord::Base
belongs_to :user
has_many :votes, :as => :votable
投票架构:
t.integer "upvote"
t.integer "downvote"
t.string "votable_type"
t.integer "votable_id"
t.integer "user_id"
后控制器:
def community
@post = @votable = Post.all
end
在我的视图页面(这里的事情变得棘手):
<% @post.each do |post| %>
<div class="eachpostrate">
<% if signed_in? then %>
<%= form_for [post, Vote.new] do |f| %>
<%= f.hidden_field :downvote, :value => "0" %>
<%= f.hidden_field :upvote, :value => "1" %>
<%= f.submit "8", :class => "upvotethumbup" %>
<% end %>
<% if post.votes.empty? then %>
<span class="upvotecount">
<p> 0 </p>
</span>
<% else %>
<% @upcount = [] %>
<% @downcount = [] %>
<span class="upvotecount">
<p>
<% post.votes.each do |vote| %>
<% @upcount << vote.upvote %>
<% @downcount << vote.downvote %>
<% end %>
<% @total = @upcount.sum - @downcount.sum %>
<%= @total %>
</p>
</span>
<% end %>
我使用nilbus提供的指示解决了这个问题,但将得分方法放入我的帖子模型而不是投票模型
def score
self.votes.upvotes.count - self.votes.downvotes.count
end
否则,我的帖子现在根据Upvote订购!感谢大家!
答案 0 :(得分:3)
您应该计算Post模型中的upvotes,downvotes和total的数量。通常,尽可能在模型中放置与模型相关的代码和逻辑,而不是在视图中。这样你就可以在其他视图中再次使用它,并且它在逻辑上更加分组。
特别是在这种情况下,您将要使用模型协会提供的方法以及范围。
class Vote < ActiveRecord::Base
scope :upvotes, where(:upvote => 1)
scope :downvotes, where(:downvote => 1)
end
使用这些范围,您可以非常轻松地计算每个帖子的投票数。
upvotes = post.votes.upvotes.count
downvotes = post.votes.downvotes.count
total = post.votes.count
您可以通过从upvotes中减去downvotes来计算投票得分。
class Vote < ActiveRecord::Base
def score
upvotes.count - downvotes.count
end
end
然后,您可以使用该分数对帖子进行排序,然后像您在视图中一样循环播放。
@posts = @posts.sort_by(&:score)
为了获得最佳效果,首次加载帖子时包含所有投票是一个好主意。为此,您可以在控制器中使用include
。否则,在计算分数时,它将不得不进行额外的查询以查找投票。
def community
@post = @votable = Post.includes(:votes).all
end
顺便说一句 - 您是否有任何理由创建具有相同内容的两个变量(@ post和@votable)?
答案 1 :(得分:1)
posts.sort {|x, y| (x.votes.collect(&:upvote).size - x.votes.collect(&:downvote).size) <=> (y.votes.collect(&:upvote).size - y.votes.collect(&:downvote).size) }