Rails ActiveRecords с собственными атрибутами + идентификаторы связанных объектов

У меня есть довольно простые ассоциации ActiveRecords, подобные таким (в частности, в Rails 4):

  • В организации много пользователей
  • Пользователь принадлежит к организации

Но с точки зрения запросов ActiveReocord, каков оптимальный способ построения запроса для возврата массива организаций, каждая из которых имеет свой собственный массив идентификаторов пользователей, связанных с самой собой? В принципе, я хотел бы вернуть следующую структуру данных:

#<ActiveRecord::Relation [#<Organization id: 1, name: "org name",.... user_ids: [1,2,3]>, <Organization id: 2...>]>

... или еще больше перегнать его в JSON:

[{id: 1, name: 'org name', ... user_ids: [1,2,3]}, {...}]

где users не является частью таблицы Organizations, а просто атрибутом, созданным на лету ActiveRecord.

Заранее спасибо.


РЕДАКТИРОВАТЬ: Попробовав несколько вещей, я придумал что-то, что вернуло результат в том формате, который я искал. Но я до сих пор не уверен (и не убежден), что это самый оптимальный запрос:

Organization.joins(:users).select("organizations.*, '[#{User.joins(:organization).pluck(:id).join(',')}]' as user_ids").group('organizations.id')

В качестве альтернативы подход JBuilder/Rabl, предложенный @Kien Thanh, кажется очень разумным и доступным. Считается ли это лучшей практикой в ​​настоящее время для разработки API на основе Rails (в приложении полностью отделены внутренние и внешние части)?


person poweratom    schedule 22.10.2014    source источник
comment
Вы должны посмотреть этот скринкаст Jbuilder, чтобы создать данные JSON, как вы хотите. .   -  person Thanh    schedule 23.10.2014
comment
Я искал прямой запрос ассоциации ActiveRecord. Но Jbuilder/Rabl кажутся чище и легче усваиваются. Спасибо!   -  person poweratom    schedule 23.10.2014


Ответы (1)


Единственное, что нужно учитывать при работе с библиотечными решениями, такими как JBuilder или Rabl, — это следить за производительностью при сборке json.

Что касается вашего запроса, используйте includes вместо joins, чтобы вернуть данные.

orgs = Organization.includes(:users)

Вы не должны группировать свои результаты таким образом (если только группа не была предназначена для некоторого совокупного значения).

ActiveRecord::Relation дает вам несколько автоматических вспомогательных методов, одним из которых является association_ids.

Итак, если вы создадите свой собственный JSON из хэша, вы можете сделать

orgs.map! {|o| o.attributes.merge(user_ids: o.user_ids).to_json }

EDIT: забыл добавить ссылку на has_many http://guides.rubyonrails.org/association_basics.html#has-many-association-reference

person Kris Robison    schedule 04.11.2014
comment
Если грубая производительность не вызывает беспокойства, я обнаружил, что использование таких библиотек, как Jbuilder, ActiveModelSerializers (при использовании Ember.js)... и т. д., более эффективно использует время разработки из-за их простоты использования, простой адаптации, легкой настройки. ... и т. д. Мне сразу стало очевидно, как устаревает ручная прокрутка пользовательских форматов ответов JSON после всего лишь недели, когда я делал это сам. Я скучаю по опытным парням из бэкенда, которые делают всю эту тяжелую работу за меня. ;) - person poweratom; 08.11.2014
comment
Согласованный. Я только что столкнулся с этой проблемой в последней компании, в которой я работал. RABL делал наш API неприемлемо медленным. В итоге один из наших инженеров самостоятельно создал для нас набор ответчиков, поэтому я всегда добавляю предостережение в начале. - person Kris Robison; 22.11.2014