0

データベース構造に基づいてjson配列(実際には文字列)を作成しようとしています。私は次の関係を持っています:

Country > State > City

私が今やっている方法は非常に非効率的です(N + 1):

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

次に、Country モデルでは次のようにします。

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

どうすればこれをより効率的に行うことができますか?

4

2 に答える 2

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 をオーバーライドすることを検討することをお勧めします。それに関する情報はウェブ上にたくさんあります。

于 2013-07-09T22:02:18.787 に答える
1

json に変換するときに含めるモデルを指定できます。

country.to_json(:include => {:states => {:include => :cities}})

http://apidock.com/rails/ActiveRecord/Serialization/to_jsonを確認してください

于 2013-07-09T18:16:30.103 に答える