Я пытаюсь объединить данные из модели ActiveRecord
с внешними данными, связанными с каждым объектом, и я пытаюсь найти чистый и эффективный способ сделать это.
Я, очевидно, могу определить метод экземпляра в модели для извлечения соответствующих внешних данных:
class State < ActiveRecord::Base
def counties
@counties ||= fetch_external_data(state: name)['counties']
end
end
State.find_by_name('Alabama').counties
Но если у меня есть коллекция объектов (через ActiveRecord::Relation
), то это приведет к N + 1 запросу к этому внешнему источнику данных.
State.where(name: %w[Alabama Georgia]).map(&:counties)
В идеале, я бы с нетерпением ждал загрузки всех данных из внешнего источника данных, а затем использовал бы метод экземпляра counties
для доступа к данным из этого «общего» объекта. Я мог бы сделать это, используя метод класса:
class State < ActiveRecord::Base
attr_accessor :counties
def self.with_counties
# Get external data for all states in our scope
counties = fetch_external_data(states: pluck(:name))
# Group by the state
counties_by_state = counties.group_by { |c| c['state'] }
# Now hydrate all of the state models and set the counties
all.map do |state|
state.counties = counties_by_state.dig(state.name, 'counties')
end
end
end
Несмотря на то, что это возможно, я не могу продолжать цепочку прицелов после использования State.where(name: %w[Alabama Georgia]).with_counties
, и мне кажется, что с ним можно работать более элегантно.
Существует ли четкий способ «загружать» данные, подобные этой (т. Е. Возможность установить «данные сбора» для объекта ActiveRecord::Relation
, к которому можно получить доступ при гидратации записи)? Если у меня есть класс, представляющий этот интерфейс внешних данных, есть ли методы, которые я мог бы определить для этого класса, чтобы он работал с State.includes(:counties)
или State.eager_load(:counties)
?
Будем благодарны за любые мысли или предложения.