Как я могу сохранить кучу объектов ActiveRecord и отношений в Rails? - PullRequest
2 голосов
/ 07 сентября 2008

Я работаю с API, который предоставляет данные о прибытии автобусов. Для каждого запроса я получаю обратно (среди прочего) список маршрутов, которые обслуживают данную остановку. Например, если в список включены результаты для автобусных маршрутов № 1, 2 и 5, то я знаю, что они служат этой остановке.

У меня установлено отношение «многие ко многим» между 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) Добавьте отношение к текущей остановке, если он еще не существует.

Есть ли лучший способ сделать это, например, получить кучу данных в памяти и выполнить некоторую обработку на стороне сервера приложений, чтобы избежать множества обращений к базе данных, которые я сейчас выполняю?

Ответы [ 3 ]

1 голос
/ 21 июня 2012

Попробуйте этот драгоценный камень: https://github.com/seamusabshere/upsert

Документы говорят, что это на 80% быстрее, чем find_or_create_by

1 голос
/ 07 сентября 2008

Если я правильно понял, у вас (должно быть) 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 голосов
/ 06 марта 2012

Вероятно, есть хороший способ очистить вызов stop, но он довольно легко его очищает, если я правильно представляю, как структурированы маршруты.

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...