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.

This commit is contained in:
Thorsten Eckel 2017-10-18 11:21:10 +02:00
parent 34ec90bd73
commit 5afb92dbdc
3 changed files with 28 additions and 7 deletions

View file

@ -108,13 +108,33 @@ returns
cache = Cache.get(key) cache = Cache.get(key)
return cache if cache return cache if cache
# get relations
attributes = self.attributes attributes = self.attributes
self.class.reflect_on_all_associations.map do |assoc| relevant = %i(has_and_belongs_to_many has_many)
next if association_attributes_ignored.include?(assoc.name) eager_load = []
real_ids = assoc.name.to_s[0, assoc.name.to_s.length - 1] + '_ids' pluck = []
next if !respond_to?(real_ids) keys = []
attributes[real_ids] = send(real_ids) 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 end
# special handling for group access associations # special handling for group access associations

View file

@ -10,7 +10,7 @@ module HasGroups
after_create :check_group_access_buffer after_create :check_group_access_buffer
after_update :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 group_through_identifier
has_many :groups, through: group_through_identifier do has_many :groups, through: group_through_identifier do

View file

@ -29,6 +29,7 @@ class ObjectCacheTest < ActiveSupport::TestCase
user1.organization_id = nil user1.organization_id = nil
user1.save user1.save
org.reload
assets = org.assets({}) assets = org.assets({})
assert_equal(org.member_ids.sort, assets[:Organization][org.id]['member_ids'].sort) assert_equal(org.member_ids.sort, assets[:Organization][org.id]['member_ids'].sort)