如何在视图中按变量排序数组

时间:2012-05-02 22:05:21

标签: ruby-on-rails ruby ruby-on-rails-3 ruby-on-rails-3.1

第一篇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订购!感谢大家!

2 个答案:

答案 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) }