From ffa87ef7bc7498cb5979631bf79eb11dbb8bab77 Mon Sep 17 00:00:00 2001 From: Tony Goncalves Date: Fri, 14 Sep 2018 13:48:17 +0100 Subject: [PATCH] Use select+joins in a scope to speed up the #index action --- app/controllers/organizations_controller.rb | 6 +++- app/models/organization.rb | 35 +++++++++++++++++++ app/views/organizations/_hq_list.html.erb | 4 +-- .../organizations/_organization.json.jbuilder | 12 +++---- 4 files changed, 47 insertions(+), 10 deletions(-) diff --git a/app/controllers/organizations_controller.rb b/app/controllers/organizations_controller.rb index 5265874..f9a892c 100644 --- a/app/controllers/organizations_controller.rb +++ b/app/controllers/organizations_controller.rb @@ -6,7 +6,11 @@ class OrganizationsController < ApplicationController # GET /organizations # GET /organizations.json def index - @organizations = Organization.all + @organizations = if request.format.html? + Organization.with_hq_names_and_store_count.all + else + Organization.with_hq_and_store_names.all + end end # GET /organizations/1 diff --git a/app/models/organization.rb b/app/models/organization.rb index 28b4868..3f8a1e6 100644 --- a/app/models/organization.rb +++ b/app/models/organization.rb @@ -3,4 +3,39 @@ class Organization < ApplicationRecord has_many :hqs has_many :stores, through: :hqs + + scope :with_hq_names_and_store_count, -> do + select(%( + organizations.*, + (SELECT array_agg( + hqs.name || + ':' || + countries.name || + '(' || + (SELECT count(id) FROM stores WHERE stores.hq_id = hqs.id) || + ')' + ) + FROM hqs + JOIN countries ON countries.id = hqs.country_id + WHERE hqs.organization_id = organizations.id + ) AS hq_data + )) + end + + scope :with_hq_and_store_names, -> do + select(%( + organizations.*, + (SELECT array_agg(json_build_object( + 'id', hqs.id, + 'name', hqs.name, + 'country_name', countries.name, + 'store_count', (SELECT count(id) FROM stores WHERE stores.hq_id = hqs.id), + 'store_list', (SELECT array_agg(json_build_object('id', id, 'name', name)) FROM stores WHERE stores.hq_id = hqs.id) + )) + FROM hqs + JOIN countries ON countries.id = hqs.country_id + WHERE hqs.organization_id = organizations.id + ) AS hq_data + )) + end end diff --git a/app/views/organizations/_hq_list.html.erb b/app/views/organizations/_hq_list.html.erb index 4b4f9d6..8ef0992 100644 --- a/app/views/organizations/_hq_list.html.erb +++ b/app/views/organizations/_hq_list.html.erb @@ -1,3 +1,3 @@ -<% organization.hqs.each do |hq| %> - <%= hq.name %>: <%= hq.country.name %> (<%= hq.stores.count %> stores)
+<% organization.hq_data.each do |hq| %> + <%= hq %>
<% end %> diff --git a/app/views/organizations/_organization.json.jbuilder b/app/views/organizations/_organization.json.jbuilder index 4338b09..8c2b7eb 100644 --- a/app/views/organizations/_organization.json.jbuilder +++ b/app/views/organizations/_organization.json.jbuilder @@ -4,13 +4,11 @@ json.extract! organization, :id, :name, :address, :contact_name, :contact_phone, json.url organization_url(organization, format: :json) -json.hqs organization.hqs do |hq| - json.extract! hq, :id, :name +json.hqs organization.hq_data do |hq| + json.extract! hq, 'id', 'name' - json.country hq.country.name - json.store_count hq.stores.count + json.country hq['country_name'] + json.store_count hq['store_count'] - json.stores hq.stores do |store| - json.extract! store, :id, :name - end + json.stores hq['store_list'] end