2017-01-06 1 views
1

Учитывая следующие модели:Как получить запрос Rails ActiveRecord для группировки объектов, принадлежащих другой модели?

ServiceCenter 
    has_many :country_codes 

CountryCode 
    belongs_to :service_center 

Что такое запрос ActiveRecord, который будет возвращать что-то вроде этого:

{ 
    "US": ["United States"], 
    "PT": ["Portugal", "Spain", "Estonia"], 
    "FR": ["France", "Germany", "Austria"] 
} 

где ключи являются country атрибутом каждого ServiceCenter а значениями являются атрибуты country_name каждого принадлежащего ему CountryCode? Другими словами, мне нужен только список того, какие CountryCodes принадлежат каждому ServiceCenter, показывая только те атрибуты.

{ 'service_centers.country': 'country_code.country_name', 'country_code.country_name' } 

Я попытался это:

CountryCode .joins(:service_center) .select('country_codes.country_name', 'service_centers.country') .group('service_centers.country')

но это возвращает:

<ActiveRecord::Relation [ 
    <CountryCode id: nil, country_name: "Portugal">, 
    <CountryCode id: nil, country_name: "United States">, 
    <CountryCode id: nil, country_name: "Portugal">.....]> 

Я также попытался ServiceCenter.joins(:country_code)...., но подобный результат - это отношение ActiveRecord с ServiceCenter объектов, идентификаторы были нулевыми , и были указаны атрибуты country.

Я посмотрел ответы, подобные этому: Get all records grouped by field from association and sorted by count in group, но мне не нужен счет.

Буду признателен за любую помощь в этом!

+0

Это трудно полностью достичь в базе данных MySQL, это не имеет типа данных массива/hstore (например, в postgresql), поэтому вы не можете делать преобразования в хэш-подобную структуру данных. – MikDiet

+0

А, возможно, это то, чего мне не хватает. У меня такое чувство, что я ЗНАЮ, что это возможно, и я видел что-то подобное раньше, но это, вероятно, было w/Postgresql. –

ответ

1

Не рекомендуется получать все записи, как показано ниже, поскольку проблема будет связана с оптимизацией. Но, для вас понимания, вы можете попробовать:

hash = {} 

ServiceCenter.all.each do |service_center| 
    hash[service_center.country] = service_center.country_codes.pluck(:country_name) 
end 

выход hash будет, как, например:

{ 
    "US": ["United States"], 
    "PT": ["Portugal", "Spain", "Estonia"], 
    "FR": ["France", "Germany", "Austria"] 
} 

Примечание: Hash не может иметь несколько значений, как вы указали, его должен быть в виде массива.

EDIT

Не совсем то, что вы хотите, но это может немного помочь:

ServiceCenter.joins(:country_codes).group("service_center_id").pluck("service_centers.country, GROUP_CONCAT(country_codes.country_name)") 

Выход

[["US", "United States"], ["PT", "Portugal, Spain, Estonia"], ["FR", "France, Germany, Austria"]] 
+0

Спасибо @Abhi. Да, я рассматривал это как раз с Ruby, но я просто задаюсь вопросом, есть ли способ сделать это с помощью ActiveRecord. Вы упомянули проблему оптимизации - думаете ли вы о памяти или времени? Каким будет преимущество оптимизации с Ruby vs. Arel? –

+1

О, неважно, вопрос оптимизации - я его неправильно прочитал. Я понимаю что ты имеешь ввиду. Вызов '.each' на' ServiceCenter.all.включает в себя (: country_codes) ', сделает его немного более результативным. –

+1

Он делает, спасибо! Я не знал о GROUP_CONCAT - очень полезен в этом случае. –

Смежные вопросы