module Switchman::ActiveRecord::Preloader::Association
Public Instance Methods
load_records()
click to toggle source
significant changes:
* partition_by_shard the records_for call * re-globalize the fetched owner id before looking up in the map
# File lib/switchman/active_record/association.rb, line 102 def load_records # owners can be duplicated when a relation has a collection association join # #compare_by_identity makes such owners different hash keys @records_by_owner = {}.compare_by_identity if owner_keys.empty? raw_records = [] else # determine the shard to search for each owner if reflection.macro == :belongs_to # for belongs_to, it's the shard of the foreign_key partition_proc = lambda do |owner| if owner.class.sharded_column?(owner_key_name) Shard.shard_for(owner[owner_key_name], owner.shard) else Shard.current end end elsif !reflection.options[:multishard] # for non-multishard associations, it's *just* the owner's shard partition_proc = ->(owner) { owner.shard } end raw_records = Shard.partition_by_shard(owners, partition_proc) do |partitioned_owners| relative_owner_keys = partitioned_owners.map do |owner| key = owner[owner_key_name] if key && owner.class.sharded_column?(owner_key_name) key = Shard.relative_id_for(key, owner.shard, Shard.current(klass.connection_classes)) end convert_key(key) end relative_owner_keys.compact! relative_owner_keys.uniq! records_for(relative_owner_keys) end end @preloaded_records = raw_records.select do |record| assignments = false owner_key = record[association_key_name] if owner_key && record.class.sharded_column?(association_key_name) owner_key = Shard.global_id_for(owner_key, record.shard) end owners_by_key[convert_key(owner_key)].each do |owner| entries = (@records_by_owner[owner] ||= []) if reflection.collection? || entries.empty? entries << record assignments = true end end assignments end end
owners_by_key()
click to toggle source
significant change: globalize keys on sharded columns
# File lib/switchman/active_record/association.rb, line 163 def owners_by_key @owners_by_key ||= owners.each_with_object({}) do |owner, result| key = owner[owner_key_name] key = Shard.global_id_for(key, owner.shard) if key && owner.class.sharded_column?(owner_key_name) key = convert_key(key) (result[key] ||= []) << owner if key end end
records_for(ids)
click to toggle source
Copypasta from Activerecord but with added global_id_for goodness.
# File lib/switchman/active_record/association.rb, line 86 def records_for(ids) scope.where(association_key_name => ids).load do |record| global_key = if model.connection_classes == UnshardedRecord convert_key(record[association_key_name]) else Shard.global_id_for(record[association_key_name], record.shard) end owner = owners_by_key[convert_key(global_key)].first association = owner.association(reflection.name) association.set_inverse_instance(record) end end
scope()
click to toggle source
significant change: don't cache scope (since it could be for different shards)
# File lib/switchman/active_record/association.rb, line 173 def scope build_scope end