From 5afb92dbdcefacf8b8a06aa0451c67f1dfc6a501 Mon Sep 17 00:00:00 2001 From: Thorsten Eckel Date: Wed, 18 Oct 2017 11:21:10 +0200 Subject: [PATCH] Refactoring: Improved lookup of association IDs by performing one JOIN instead of multiple SELECTs. This is especially usefull for systems where the DB runs on a separated system. --- .../application_model/can_associations.rb | 32 +++++++++++++++---- app/models/concerns/has_groups.rb | 2 +- test/unit/object_cache_test.rb | 1 + 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/app/models/application_model/can_associations.rb b/app/models/application_model/can_associations.rb index 2b5ac620a..058087300 100644 --- a/app/models/application_model/can_associations.rb +++ b/app/models/application_model/can_associations.rb @@ -108,13 +108,33 @@ returns cache = Cache.get(key) return cache if cache - # get relations attributes = self.attributes - self.class.reflect_on_all_associations.map do |assoc| - next if association_attributes_ignored.include?(assoc.name) - real_ids = assoc.name.to_s[0, assoc.name.to_s.length - 1] + '_ids' - next if !respond_to?(real_ids) - attributes[real_ids] = send(real_ids) + relevant = %i(has_and_belongs_to_many has_many) + eager_load = [] + pluck = [] + keys = [] + self.class.reflect_on_all_associations.each do |assoc| + next if relevant.exclude?(assoc.macro) + + assoc_name = assoc.name + next if association_attributes_ignored.include?(assoc_name) + + eager_load.push(assoc_name) + pluck.push("#{assoc.table_name}.id") + keys.push("#{assoc_name.to_s.singularize}_ids") + end + + if eager_load.present? + ids = self.class.eager_load(eager_load) + .where(id: id) + .pluck(*pluck) + + if keys.size > 1 + values = ids.transpose.map(&:compact).map(&:uniq) + attributes.merge!( keys.zip( values ).to_h ) + else + attributes[ keys.first ] = ids.compact + end end # special handling for group access associations diff --git a/app/models/concerns/has_groups.rb b/app/models/concerns/has_groups.rb index 4d420059a..9896ee3f0 100644 --- a/app/models/concerns/has_groups.rb +++ b/app/models/concerns/has_groups.rb @@ -10,7 +10,7 @@ module HasGroups after_create :check_group_access_buffer after_update :check_group_access_buffer - association_attributes_ignored :groups + association_attributes_ignored :groups, group_through_identifier has_many group_through_identifier has_many :groups, through: group_through_identifier do diff --git a/test/unit/object_cache_test.rb b/test/unit/object_cache_test.rb index 26d9b05ec..4ab4ee840 100644 --- a/test/unit/object_cache_test.rb +++ b/test/unit/object_cache_test.rb @@ -29,6 +29,7 @@ class ObjectCacheTest < ActiveSupport::TestCase user1.organization_id = nil user1.save + org.reload assets = org.assets({}) assert_equal(org.member_ids.sort, assets[:Organization][org.id]['member_ids'].sort)