2010-04-16 2 views
0

Ruby on Rails를 사용하여 간단한 블로그 응용 프로그램을 만들었습니다. 내 '투표'된 게시물을 /views/posts/index.html.erb보기에 표시하려고합니다. 다음은 기본 사항입니다.내 블로그에 가장 인기있는 게시물 표시 - Ruby on Rails

투표 테이블을 만들고 사용자가 /views/posts/show.html.erb 페이지의 게시물에 '투표'할 수있게했습니다. VotesController는 post_id를 Votes 테이블 열 post_id에 전달하고 해당 게시물의 투표 수를 ajax를 통해 동일한 표시 페이지로 반환합니다.

class Vote 
    belongs_to :post` 
end 

class Post 
    has_many :votes 
end 

내가 가진 게시물에 의해 주문 게시물 제목과는 투표 된 시간의 양, /views/posts/index.html.erb에 표시 할 것 최고 투표 수. 내가합니다 (/views/posts/show.html.erb 페이지에서)를 표시 할 수있게되었습니다 아래의 코드가 post_id를위한 투표 테이블과 vote_count에서 post_id를 가진

편집 . 즉 '55 (7) '이다. 궁금해지면 어떻게 든 post_title을 vote 테이블 (post_title 열)에 전달한 다음 post_id 대신 post_title을 표시 할 수 있습니다. 다음은이를 수행하는 코드입니다. 다음과 같은

class PostsController < ApplicationController 

    def index 
     @tag_counts = Tag.count(:group => :tag_name, 
      :order => 'count_all DESC', :limit => 20) 
     @vote_counts = Vote.count(:group => :post_id, :limit => 5) 

     conditions, joins = {}, nil 
     unless(params[:tag_name] || "").empty? 
      conditions = ["tags.tag_name = ? ", params[:tag_name]] 
      joins = :tags 
     end 
     @posts=Post.all(:joins => joins, :conditions=> conditions, :order => 'created_at DESC').paginate :page => params[:page], :per_page => 5 

     respond_to do |format| 
      format.html # index.html.erb 
      format.xml { render :xml => @posts } 
      format.json { render :json => @posts } 
      format.atom 
     end 
     end 

VotesController

class VotesController < ApplicationController 

    def create 
    @post = Post.find(params[:post_id]) 
    @vote = @post.votes.create!(params[:vote]) 

     respond_to do |format| 
     format.html { redirect_to @post} 
     format.js 
    end 
    end 
end 

/views/posts/index.html.erb

Most Liked Posts<hr/> 
     <% @vote_counts.each do |post_id, vote_count| %>  
       <div id="tag-wrapper"> 
        <%= link_to(post_id, posts_path(:post_id => post_id)) %> 
        (<%=vote_count%>)</div> 
     <% end %> 
+0

당신이 [이 게시물]에서와 거의 같은 질문을 (요구하는지 알기나 해 http://stackoverflow.com/questions/2634981/how- 유사한 - 레코드 - 표시 - 개수 - 루비 - 온 - 레일)에 대한 검색을 수행 할 수 있습니까? 대답은 동일합니다. ** 요청 시간에 값을 계산하지 말고 counter_cache를 사용하십시오. –

답변

7

당신은

class User 
acts_as_voter 
end 

posts 테이블에 vote_total 열 (정수)를 추가 이것에 대한 vote_fu 플러그인을 사용 (kandadaboggu-vote_fu 버전을 사용) 할 수 있습니다.

class Post 
acts_as_voteable :vote_counter => true 
end 

이제 다음을 수행 할 수 있습니다

user.vote_for(post)  # vote up 
user.vote_against(post) # vote down 
post.vote_total   # sum of +ve and -ve votes 
post.vote_count   # count of votes 

당신이 vote_counter 지침, 투표 전체가 posts 테이블에 유지 사용하는 경우. vote_total을 계산하는 데 추가 SQL이 필요하지 않습니다.

이 vote_total에 의해 게시물을 정렬하려면 다음을 수행하십시오

Posts.all(:order => "vote_total DESC") 

공개 나는 kandadaboggu-vote_fu 보석을 유지

.2

당신은이 기능을 구현하려면 다음 코드를 사용할 수 있습니다

Post.all(:joins => :votes, :select => "posts.*, count(*) as vote_total", 
    :group => "votes.post_id", :order => "vote_total DESC", :limit => 10) 

편집 :

편집하는 것은

현재 스키마에서이를 구현하려면 다음을 수행 할 수 있습니다 현재 논리로 작업 할 수 있습니다. Rails는 INNER 조인을 사용하므로 투표가없는 게시는 선택되지 않습니다. 게시물이 생성 될 때 항상 한 번 투표하면이 문제를 피할 수 있습니다.

귀하의 paginate 전화를 수정했습니다. 현재의 논리는 매우 비효율적이다. 페이지 매김은 DB에서 반환 된 배열에 적용되므로 페이지 매김을 수행하기 전에 전체 결과 집합이로드됩니다. 원칙적으로 paginateall과 같은 두 개의 추가 매개 변수로 처리하십시오.

아래의 SQL은 시스템 리소스에 부담을줍니다. 을 posts 테이블에 저장하여 최적화해야 할 수도 있습니다. 게시물의 생성시에 투표에 대한

conditions, joins = {}, :votes 

unless(params[:tag_name] || "").empty? 
    conditions = ["tags.tag_name = ? ", params[:tag_name]] 
    joins = [:tags, :votes] 
end 
@posts=Post.paginate(
      :select => "posts.*, count(*) as vote_total", 
      :joins => joins, 
      :conditions=> conditions, 
      :group => "votes.post_id", 
      :order => "vote_total DESC", 
      :page => params[:page], :per_page => 5) 

편집 3

논리. 게시물에 대한

class Vote 
    belongs_to :user 
    belongs_to :post 
end 

class Post 
    belongs_to :user 
    after_create :self_vote 

    def self_vote 
    # I am assuming you have a user_id field in `posts` and `votes` table. 
    self.votes.create(:user => self.user) 
    end 
end 

반복 코드 :

<% @posts.each do |post| %> 
<p><%= link_to(post.title, post_path(post)) %></p> 
<p> 
    Created <%= time_ago_in_words(post.created_at) %>. 
    Votes <%= post.vote_total %> 
</p> 
<% end %> 
+0

나는 그 장면을 줄 것이라고 생각하지만, 그렇게하지 않고서는 post_title을 vote 테이블에 post_title이라는 열로 전달한 다음 @vote_counts = Vote.count (: group => : post_id, limit => 5) 컨트롤러에서보기에서 post_id w/post_title 바꾸기? 그것을 시도했지만 투표 # 색인에서 post_id를 전달할 수없는 것 같습니다. – bgadoci

+0

답변이 한 번 업데이트되었습니다. –

+0

"사용할 수 있습니다 ..."는 "사용해야합니다 ..."보다 적절할 것이라고 생각합니다. 그 외에도 제공되는 정보가 도움이 될 것 같습니다. +1 –

-1

사용 MySQL의 query.Something는 RHTML

@posts=Post.find_by_sql("select p.post, count(v.vote) as vote from posts p, votes v where v.post_id=p.id group by p.id order by vote DESC") 

for post in @posts 
    post.post 
    post.vote 
end 
+0

하드 코딩 SQL은 ActiveRecord 기능이 내장되어있어이를 수행하는 최악의 방법입니다. –