2012-07-07 2 views
2

사용자는 리소스를 제출하고 주석을 게시 할 수 있습니다.관련 레코드 수별 레코드 정렬

리소스 및 의견을 제출 한 사용자를 선택하고 가장 많은 리소스와 의견을 가장 많이 제출 한 사용자의 결과를 정렬하여 가장 활동적인 사용자를 표시하려고합니다.

**Resource** 
has_many :users, :through => :kits 
has_many :kits 
belongs_to :submitter, class_name: "User" 

**User** 
has_many :resources, :through => :kits 
has_many :kits 
has_many :submitted_resources, class_name: "Resource", foreign_key: "submitter_id" 

**Kits** 
belongs_to :resource 
belongs_to :user 

**Comments** 
belongs_to :user 

저는 Rails에서 이런 종류의 sql에 익숙하지 않습니다. 이 레코드 집합을 어떻게 가져올 수 있습니까? 먼저

답변

2

, 당신은 사용자 모델에 코멘트 연결을 추가해야합니다 :이

has_many :comments 

을, 간단한 해결책이 작업을 수행하는 것입니다 : 이것은 아주 느린 얻을 것이다

User.all.sort do |a,b| 
    (a.submitted_resources.count + a.comments.count) <=> (b.submitted_resources.count + b.comments.count) 
end 

, 그래서 당신이 더 잘하고 싶다면 당신은 카운터 캐쉬를 추가하기를 원할 것입니다. 마이그레이션에서 :이 마이그레이션을 실행하면

def up 
    add_column :users, :submitted_resources_count, :integer 
    add_column :users, :comments_count, :integer 

    User.reset_column_information 

    User.find_each do |u| 
    u.update_attributes! \ 
     :submitted_resources_count => u.submitted_resources.count, 
     :comments_count => u.comments.count 
    end 
end 

def down 
    add_column :users, :submitted_resources_count 
    add_column :users, :comments_count 
end 

, 당신은 원래 쿼리를 변경할 수 있습니다 매우 효율적으로 적절한 순서로 모든 사용자를 반환합니다

User.select('*, (submitted_resources_count + comments_count) AS activity_level').order('activity_level DESC') 

이, 그리고 보너스 각 사용자로 정확히 제출 된 리소스 + 코멘트 수를 줄 수있는 activity_level이라는 읽기 전용 속성을 갖게됩니다.

+0

감사합니다. Tanzeeb, 질문이 있습니다. 1. def_column : users, : def_downs 메소드의 submitted_resources_count가 있어야합니까? 2.이 마이그레이션을 실행하지만 User.find_each 메소드는 | u | 이번에 마이그레이션이 실행될 때만 실행됩니다. 그렇다면 가장 적극적인 사용자를 찾아야 할 때마다이를 실행 범위에 넣거나 응용 프로그램의 다른 곳에 두어야합니까? – chell

+0

좋은 질문입니다. 1) 예. down 메소드는 up을 취소해야하고, up은 두 개의 컬럼을 작성하기 때문에 down은이를 제거해야합니다. 2) 마이그레이션의 업데이트가 초기 개수를 설정하지만 다시 호출 할 필요가 없습니다. Rails는 패턴 * _count와 일치하는 열을 해당 연결의 수로 자동 업데이트합니다. 세 번째 쿼리 인 User.select ...를 클래스 메서드 또는 최상위 사용자를 끌어들이는 범위로 사용할 수 있습니다. 최상위 사용자 만 얻으려면 체인 끝에 제한 (1)을 추가하십시오. –