3

第一篇 StackOverFlow 帖子,请耐心等待 :)

所以我有一个帖子模型,它与投票模型具有多态关联。

我的主要问题是按最高票数对每个帖子进行排序。我正在尝试实施 Upvote 系统。问题:我如何按最高票排序帖子?(@全部的)

看来我的视图中有代码(@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 提供的说明解决了这个问题,除了将 score 方法放在我的 Post 模型中而不是 Vote 模型中

 def score 
self.votes.upvotes.count - self.votes.downvotes.count 
  end

否则,我的帖子现在是根据 Upvote 排序的!感谢大家!

4

2 回答 2

3

您应该计算 Post 模型中的赞成票、反对票和总数。一般来说,尽量在模型中而不是视图中放置尽可能多的与模型相关的代码和逻辑。这样您也可以在其他视图中再次使用它,并且它的分组更合乎逻辑。

特别是在这种情况下,您需要使用模型关联提供的方法以及范围。

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

您可以通过从赞成票中减去反对票来计算投票的分数。

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)的原因是什么?

于 2012-05-02T22:25:41.800 回答
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) }
于 2012-05-02T22:18:45.647 回答