2010-02-26 107 views
1

嗨:我正在用rails查詢工作。最後,我想對以下內容做出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 

什麼是使用Rails來解決這個最優雅的方式?

+0

你已經試過了什麼?到目前爲止顯示你的代碼嘗試,你會得到更好的迴應。 – Timothy 2010-02-26 10:48:47

回答

1

你需要重載to_json方法:

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

然後在你的控制器做這樣的事情:

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

你將不得不使用的has_many throught從國家獲得公司。文檔在這裏:http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

對不起,我沒有時間更精確的解決方案,但希望這些指針可以幫助你。如果您有特殊問題,請隨時發表評論或打開一個新問題。

+0

謝謝!您的解決方案讓我重新走上正軌! 在 「類國家<的ActiveRecord :: Base的」 我現在有: 高清to_json 哈希= { 「國家名稱」=> self.name, 「量公司」=> self.companies.size} hash.to_json 結束 這似乎工作。 – Sney 2010-02-26 12:43:39

+0

如果你只是想要計數,你不應該使用c.companies.size,因爲它會加載所有的記錄(這很浪費)。改爲使用c.companies.count。 – psyho 2010-02-26 13:56:06

+0

@Sney調用to_json方法'to_json'應該導致'循環' – 2012-02-24 16:03:04

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:我在Address中添加了「:counter_cache =>:companies_count」以及名爲「companies_count」的列,但我仍然有n + 1個SQL查詢。如何讓計數器緩存最終運行? #2:通過發佈單個SQL查詢,我可以獲得所有國家,即使是那些沒有公司的國家。當我追加「:conditions =>'companies_count> 0'」我沒有結果。有沒有辦法將這個限制添加到查詢中,還是必須通過Ruby中的數組? – Sney 2010-02-26 15:09:59

+0

名爲companies_count的列應該進入國家模式(國家/地區表)。您還需要記住它會自行設置它的初始值。你需要像Company.update_all('companies_count =(SELECT count(*)FROM addresses WHERE country_id = countries.id)')來設置正確的初始值。之後,你應該能夠像你想要的那樣查詢國家。 – psyho 2010-02-27 21:34:58

+0

我將「Company.update_all ...」更改爲「Country.update_all ...」。我還必須將「countries = Country.find(:all).select {| c | c.companies.count> 0}」改爲「countries = Country.find(:all)」。選擇{| C | c.companies_count> 0}「我認爲rails會用」count「方法做一些魔術,但是看起來,我必須明確地調用只讀屬性」companies_count「。 – Sney 2010-02-27 22:40:22