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が提供する指示を使用してこれを解決しました

 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) を持つ 2 つの変数を作成する理由は何ですか?

于 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 に答える