2010-02-26 5 views
1

안녕하세요 : 저는 레일 쿼리에 어려움을 겪고 있습니다. 마지막으로, 다음 내용으로 JSON 응답을 작성하려고합니다. 주소가있는 회사가 하나 이상있는 국가의 목록과 국가에 거주하는 회사 수를 계산합니다.Ruby on Rails로 쿼리하기

class Country < ActiveRecord::Base 
    has_many :addresses 
end 

class Address < ActiveRecord::Base 
    belongs_to :country 
    belongs_to :company 
end 

class Company < ActiveRecord::Base 
    has_one :address 
end 

레일과이 문제를 해결하는 가장 우아한 방법은 무엇입니까 : 여기 내 간단한 모델 구조인가? 그런 일을 컨트롤러에 다음

class Country < ActiveRecord::Base 
    has_many :addresses 
    def to_json 
     # format your country as json with all the elements you need 
    end 
end 

:

+0

이미 시도한 바가 있습니까? 지금까지 코드 시도를 보여 주면 더 나은 응답을 얻을 수 있습니다. – Timothy

답변

1

당신은 to_json 메서드를 오버로드 할 필요

countries = Country.find(:all).select{|c| c.companies.size > 0 } 
json = countries.collect{|c| c.to_json } 

당신은 국가에서 회사를 얻을 수 has_many의 축복하는을 사용해야합니다 . 여기에 문서 : http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

죄송합니다. 나는 더 정확한 해결책을 찾을 시간이 없지만, 이러한 포인터가 도움이되기를 바랍니다. 특정 문제가있는 경우 자유롭게 의견을 말하거나 새 질문을 열어보십시오.

+0

감사합니다. 당신의 솔루션은 나를 다시 궤도에 오르게했습니다! 에서 "클래스 나라 <액티브 :: 자료"지금이 : 데프 해시 = { "국가 이름"= to_json> self.name, "양 회사"=> self.companies.size} hash.to_json을 end 그게 효과가있는 것 같습니다. – Sney

+0

모든 레코드를로드하기 때문에 카운트를 원할 경우 c.companies.size를 사용하면 안됩니다 (이는 상당히 낭비입니다). 대신 c.companies.count를 사용하십시오. – psyho

+0

@Sney to_json 메서드 내에서 to_json을 호출하면 'loop'이됩니다. –

1

당신은

belongs_to :country, :counter_cache => :companies_count 

그것은 N + 1 쿼리 문제에서 당신을 절약 할 국가 모델에서 기업의 수를 저장 문제를 해결하기 위해 카운터 캐시를 추가 할 수 있습니다.

또한이 같은 단일 쿼리를 실행하여도 그것을 피할 수 :

Country.find(:all, :select => 'countries.*, count(addresses.id) as companies_count', :joins => 'LEFT JOIN addresses ON addresses.country_id = countries.id', :group => 'countries.id') 

이 방법으로 반환 된 국가의 모든 해당 국가 기업의 수를 포함하는 필드 companies_count있을 것이다.

+0

힌트를 보내 주셔서 감사합니다! # 1 : "counter_cache => : companies_count"및 "companies_count"라는 열을 Address에 추가했지만 여전히 n + 1 개의 SQL 쿼리가 있습니다. 마지막으로 카운터 캐시를 작동 시키려면 어떻게합니까? # 2 : 단일 SQL 쿼리를 발행함으로써 회사가없는 사람들을 포함한 모든 국가를 얻습니다. 내가 추가 할 때 ": conditions => 'companies_count> 0'"결과가 없습니다. 이 제한을 쿼리에 추가하는 방법이 있습니까? 아니면 루비에서 배열을 통과해야합니까? – Sney

+0

companies_count라는 이름의 열은 국가 모델 (국가 테이블)에 있어야합니다. 또한 초기 값으로 설정된다는 것을 기억해야합니다. 올바른 초기 값을 설정하려면 Company.update_all ('Companies_count = (SELECT count (*) FROM addresses where country_id = countries.id)'와 같은 것이 필요합니다. 그 후에 원하는대로 국가를 쿼리 할 수 ​​있어야합니다. – psyho

+0

"Company.update_all ..."을 "Country.update_all ..."으로 변경했습니다. 또한 "countries = Country.find (: all) .select {| c | c.companies.count> 0}"to "countries = Country.find (: all)"로 변경해야했습니다.{| c | "count"메서드로 레일이 마법을 쓸 것이라고 생각했지만, 읽기 전용 속성 "enterprises_count"를 명시 적으로 호출해야합니다. – Sney

관련 문제