2008-09-07 9 views
2

私は、バス到着データを提供するAPIを使って作業しています。すべてのリクエストに対して、私はどのルートが問題のストップに役立つかのリストを(他のものの中でも)返す。たとえば、リストにバスルート#1,2、および5の結果が含まれている場合、その停止を処理することがわかります。Railsで複数のActiveRecordオブジェクトと関係をアップセットするにはどうすればよいですか?

私はRouteとStopの間に多対多のリレーションシップを設定しており、リクエストごとにこれらのアソシエーションを動的にチェックして更新したいと考えています。どのルートが停止するかを示す「マスターリスト」はありません。したがって、このデータを取得する最善の方法のようです。

私は今それをやっている方法は非常に非効率的であると信じています:

# routes is an array of [number, destination] that I build while iterating over the data 
routes.uniq.each do |route| 
    number  = route[0] 
    destination = route[1] 

    r = Route.find_by_number_and_destination(number, destination) 

    if !r 
    r = Route.new :number => number, :destination => destination 
    r.save 
    end 

    # I have to check if it already exists because I can't find a way 
    # to create a uniqueness constraint on the join table with 2 foreign keys 
    r.stops << stop unless r.stops.include? stop 
end 

は基本的に、私は私が見つけるすべてのルートの2つのことをしなければならない: 1)そうでない場合は、それを作成します。すでに存在していない場合は、2)現在のストップに関係を追加します。

私は現在やっているデータベース呼び出しの数を避けるために、メモリ内のデータの束を取得し、アプリケーションサーバー側でいくつかの処理を行うなど、より良い方法がありますか?

答えて

1

私はそれが正しいとすれば、2つのモデルが必要です。ルートモデル、およびストップモデルがあります。ここで

は、私はこれらのモデルを定義する方法は次のとおりです。

class Route < ActiveRecord::Base 
    has_and_belongs_to_many :stops 
    belongs_to :stop, :foreign_key => 'destination_id' 
end 

class Stop < ActiveRecorde::Base 
    has_and_belongs_to_many :routes 
end 

そして、ここでは、私は私のテーブルを設定します方法は次のとおりです。

create_table :routes do |t| 
    t.integer :destination_id 
    # Any other information you want to store about routes 
end 

create_table :stops do |t| 
    # Any other information you want to store about stops 
end 

create_table :routes_stops, :primary_key => [:route_id, :stop_id] do |t| 
    t.integer :route_id 
    t.integer :stop_id 
end 

最後に、ここで私が使用したいコードがあります:

# First, find all the relevant routes, just for caching. 
Route.find(numbers) 

r = Route.find(number) 
r.destination_id = destination 
r.stops << stop 

これは、わずかなSQLクエリを使用する必要があります。

0

ストップコールをクリーンアップするには良い方法がありますが、ルートがどのように構造化されているかを正しく把握していると仮定すると、

routes.uniq.each do |number, destination| 

    r = Route.find_or_create_by_number_and_destination(route[0], destination) 

    r.stops << stop unless r.stops.include? stop 

end 
1

この宝石を試してみてください: https://github.com/seamusabshere/upsert

ドキュメントは、それは限り、あなたは "バッチ" モードでそれを使用すると高速ですfind_or_create_by

+0

よりその80%高速化と言います... –

関連する問題