2014-10-21 3 views
0

나는 국가 모델과 여행 노트 모델이 있습니다. 한 국가에는 많은 여행 노트가 있고 여행 노트는 한 국가에 속합니다. 응용 프로그램/컨트롤러/countries_controller.rb에서레일 activerecord 관계 조인 테이블

class TravelNote < ActiveRecord::Base 
    default_scope { order(created_at: :desc) } 

    belongs_to :country 
    has_many :chapters 

    before_destroy { draft? } 

    validate :validates_uniqueness_of_draft, on: :create 

    enum status: { draft: 0, published: 1, archived: 2 } 
    enum advice_against: { no: 0, general: 1, tourists: 2 } 

    scope :country, ->(country_id) { where(country_id: country_id) } 

    # further methods omitted... 
end 

class Country < ActiveRecord::Base 
    default_scope { order(:iso_code) } 

    has_many :travel_notes 

end 

:/index.html.haml 응용 프로그램/뷰/국가에서

class CountriesController < ApplicationController 
    def index 
    @countries = Country.includes(:travel_notes) 
    end 
    # rest of the class omitted... 
end 

:

@countries.each do |country| 
     %tr 
      %td= link_to country.name_de, country_travel_notes_path(country) 
      %td= TravelNote.published.country(country.id).first.try :published_at 

때문에 성능 이유 내가 원하는 TravelNote.published.country (country.id) .first.try : published_at를 제거하십시오. 그 대신 동등한 SQL 쿼리의 배열 대신 더 이상 수백 개의 데이터베이스 쿼리가 없습니다 :

select * from countries 
left join travel_notes 
on countries.id=travel_notes.country_id 

어떻게하면됩니까?

+0

내가 아니다 하지만,'TravelNote.published.joins (: country) .where (: countries => {: id => country.id}) map (& : published_at)'도움이된다면 시도 할 수 있습니다 – Sontya

+0

Sontya에게 감사드립니다. 실제로 도움이되었습니다. – StandardNerd

답변

1

은 분명히 당신이하려고하는 열망 -로드 국가에 관련된 "travel_notes을"

Country.includes(:travel_notes).where(travel_notes: { status: 1}) 

그래서 코드가 될 것이다 :

class CountriesController < ApplicationController 
    def index 
    @countries = Country.includes(:travel_notes).where(travel_notes: { status: 1}) 
    end 
    # rest of the class omitted... 
end 
@countries.each do |country| 
     %tr 
      %td= link_to country.name_de, country_travel_notes_path(country) 
      %td= country.travel_notes.first.published_at 
1

게시 된 메모 만 포함하도록 사용자 지정 범위를 작성할 수 있습니다.

뭔가

scope :include_published, -> { proc do |_| 
    joins("LEFT OUTER JOIN (
     SELECT b.* 
     FROM travel_notes b 
     WHERE published = 1 
     GROUP BY b.country_id 
    ) notes_select ON notes_select.country_id = countries.id" 
    ).select("countries.*").select("#{insert what attributes you want to include }") 
    end.call(self, counted_model) } 

처럼 그런 그들이 같은 이름의 방법으로 국가 활동 기록 결과에 포함됩니다 두 번째 SELECT 절에 메모에서 원하는 속성을 포함해야합니다.

는 SQL 쿼리

내가 연관된 객체의 수를 포함하는 내 프로젝트에 있지만 위해 유사한 기술을 사용하여 ..., 난 그냥 함께 뭔가를 던졌다 예쁘게 쓸 수 있습니다.

+1

내가 뭔가를 놓치지 않는다면, 거기에'proc'가 필요하지 않습니다. –

+0

proc, comment에 대해 아마도 정확합니다. 관련된 모델에 따라 쿼리를 생성하는 모듈로 추출 했으므로 proc가 있습니다. – Albin

+0

Albin Svensson에게 감사드립니다. 멋지 네요. 다른 컨텍스트에서 여러분의 접근 방식을 확실히 사용 하겠지만,이 경우 mohameddiaa27 코드는 더 단순 해 보입니다. – StandardNerd