2013-07-09 22 views
0

我想創建一個基於我的數據庫結構的JSON數組(字符串實際)。我有以下關係:從ActiveRecord創建JSON文件,並避免N + 1

Country > State > City 

我現在做它的方式是非常innefficient(N + 1):

data = "[" + Country.all.map{ |country| 
    { 
    name: country.name, 
    states: country.states_data 
    }.to_json 
}.join(",") + "]" 

然後在國家型號:

def states_data 
    ret_states = [] 
    states.all.each do |state| 
    ret_states.push name: state.name, cities: state.cities_data 
    end 
    ret_states 
end 

然後在州模型上:

def cities_data 
    ret_cities = [] 
    cities.all.each do |city| 
    ret_cities.push name: city.name, population: city.population 
    end 
    ret_cities 
end 

如何我可以更有效地做到這一點嗎?

回答

1

急於負荷的州和城市。請小心,因爲這可能會佔用大量數據集的大量內存。請參閱文檔http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations。只要有可能,我喜歡使用連接,包括一次獲取所有數據。

#to_json也會爲您序列化數組,因此您不需要手動添加JSON位。

從上面您的代碼可以改變,像這樣:

data = Country.joins(:states => :cities).includes(:states => :cities).all.map{ |country| 
    { 
    name: country.name, 
    states: country.states_data 
    } 
}.to_json 

但你也可以去掉了_data方法的需求。

data = Country.joins(:states => :cities).includes(:states => :cities).to_json(
    :only => :name, 
    :include => { 
    :states => { 
     :only => :name, 
     :include => { 
     :cities => { 
      :only => [:name, :population] 
     } 
     } 
    } 
    } 
) 

這非常難看,因此您可能希望查看每個模型的覆蓋#as_json。網上有很多關於這方面的信息。