Class: PaperTrailDiff::LiveEndpointBatchLoader
- Inherits:
-
Object
- Object
- PaperTrailDiff::LiveEndpointBatchLoader
- Defined in:
- lib/paper_trail_diff/live_endpoint_batch_loader.rb,
sig/generated/paper_trail_diff/live_endpoint_batch_loader.rbs
Overview
Reloads current-record endpoints and their explicitly selected associations in batches.
Instance Method Summary collapse
-
#active_record_preloader ⇒ Object
: () -> untyped.
-
#batch_safe?(record, reflection) ⇒ Boolean
: (untyped, untyped) -> bool.
-
#call(records) ⇒ Hash[identity, untyped]
: (Array) -> Hash[identity, untyped].
-
#ensure_all_loaded!(records, loaded) ⇒ void
: (Array, Hash[identity, untyped]) -> void.
-
#initialize(tree:) ⇒ LiveEndpointBatchLoader
constructor
: (tree: AssociationTree) -> void.
- #load_group(model_class, records) ⇒ Array[untyped]
- #load_individually(records, reflection) ⇒ Array[untyped]
- #preload_batch(records, associations) ⇒ void
-
#preload_model_tree(model_class, records, tree) ⇒ void
: (untyped, Array, AssociationTree) -> void.
-
#preload_subtrees(records, reflections, individually:) ⇒ void
: (Array, Array[[untyped, AssociationTree]], individually: bool) -> void.
-
#preload_tree(records, tree) ⇒ void
: (Array, AssociationTree) -> void.
-
#selected_reflections(model_class, tree) ⇒ Array[[ untyped, AssociationTree ]]
: (untyped, AssociationTree) -> Array[[untyped, AssociationTree]].
- #targets(records, reflection) ⇒ Array[untyped]
- #unique_records(records) ⇒ Array[untyped]
Constructor Details
#initialize(tree:) ⇒ LiveEndpointBatchLoader
: (tree: AssociationTree) -> void
8 9 10 |
# File 'lib/paper_trail_diff/live_endpoint_batch_loader.rb', line 8 def initialize(tree:) @tree = tree end |
Instance Method Details
#active_record_preloader ⇒ Object
: () -> untyped
88 89 90 91 |
# File 'lib/paper_trail_diff/live_endpoint_batch_loader.rb', line 88 def active_record_preloader active_record = Object.const_get(:ActiveRecord) active_record.const_get(:Associations).const_get(:Preloader) end |
#batch_safe?(record, reflection) ⇒ Boolean
: (untyped, untyped) -> bool
94 95 96 97 98 99 100 101 |
# File 'lib/paper_trail_diff/live_endpoint_batch_loader.rb', line 94 def batch_safe?(record, reflection) scope = reflection.scope return false if scope && !scope.arity.zero? return true unless reflection.collection? relation = record.association(reflection.name).scope relation.limit_value.nil? && relation.offset_value.nil? end |
#call(records) ⇒ Hash[identity, untyped]
: (Array) -> Hash[identity, untyped]
13 14 15 16 17 18 19 20 21 22 |
# File 'lib/paper_trail_diff/live_endpoint_batch_loader.rb', line 13 def call(records) loaded = {} #: Hash[identity, untyped] records.group_by(&:class).each do |model_class, grouped| load_group(model_class, grouped).each do |record| loaded[Endpoint.identity(record)] = record end end ensure_all_loaded!(records, loaded) loaded end |
#ensure_all_loaded!(records, loaded) ⇒ void
This method returns an undefined value.
: (Array, Hash[identity, untyped]) -> void
125 126 127 128 129 130 131 |
# File 'lib/paper_trail_diff/live_endpoint_batch_loader.rb', line 125 def ensure_all_loaded!(records, loaded) missing = records.map { |record| Endpoint.identity(record) }.uniq - loaded.keys return if missing.empty? = 'current record endpoint could not be reloaded from the database' raise InvalidEndpointError, end |
#load_group(model_class, records) ⇒ Array[untyped]
29 30 31 32 33 34 |
# File 'lib/paper_trail_diff/live_endpoint_batch_loader.rb', line 29 def load_group(model_class, records) relation = model_class.unscoped.where(model_class.primary_key => records.map(&:id).uniq) loaded = relation.to_a preload_tree(loaded, @tree) loaded end |
#load_individually(records, reflection) ⇒ Array[untyped]
104 105 106 107 108 |
# File 'lib/paper_trail_diff/live_endpoint_batch_loader.rb', line 104 def load_individually(records, reflection) unique_records(records.flat_map do |record| Array(record.association(reflection.name).load_target) end) end |
#preload_batch(records, associations) ⇒ void
78 79 80 81 82 83 84 85 |
# File 'lib/paper_trail_diff/live_endpoint_batch_loader.rb', line 78 def preload_batch(records, associations) return if associations.empty? active_record_preloader.new( records: records, associations: associations ).call end |
#preload_model_tree(model_class, records, tree) ⇒ void
This method returns an undefined value.
: (untyped, Array, AssociationTree) -> void
46 47 48 49 50 51 52 53 |
# File 'lib/paper_trail_diff/live_endpoint_batch_loader.rb', line 46 def preload_model_tree(model_class, records, tree) batch, individual = selected_reflections(model_class, tree).partition do |reflection, _| batch_safe?(records.fetch(0), reflection) end preload_batch(records, batch.map { |reflection, _| reflection.name }) preload_subtrees(records, batch, individually: false) preload_subtrees(records, individual, individually: true) end |
#preload_subtrees(records, reflections, individually:) ⇒ void
This method returns an undefined value.
: (Array, Array[[untyped, AssociationTree]], individually: bool) -> void
66 67 68 69 70 71 72 73 74 75 |
# File 'lib/paper_trail_diff/live_endpoint_batch_loader.rb', line 66 def preload_subtrees(records, reflections, individually:) reflections.each do |reflection, subtree| children = if individually load_individually(records, reflection) else targets(records, reflection) end preload_tree(children, subtree) end end |
#preload_tree(records, tree) ⇒ void
This method returns an undefined value.
: (Array, AssociationTree) -> void
37 38 39 40 41 42 43 |
# File 'lib/paper_trail_diff/live_endpoint_batch_loader.rb', line 37 def preload_tree(records, tree) return if records.empty? || tree.empty? records.group_by(&:class).each do |model_class, grouped_records| preload_model_tree(model_class, grouped_records, tree) end end |
#selected_reflections(model_class, tree) ⇒ Array[[ untyped, AssociationTree ]]
: (untyped, AssociationTree) -> Array[[untyped, AssociationTree]]
56 57 58 59 60 61 62 63 |
# File 'lib/paper_trail_diff/live_endpoint_batch_loader.rb', line 56 def selected_reflections(model_class, tree) tree.children.map do |name, subtree| reflection = model_class.reflect_on_association(name) raise ConfigurationError, "unknown association: #{name}" unless reflection [reflection, subtree] end end |
#targets(records, reflection) ⇒ Array[untyped]
111 112 113 114 115 |
# File 'lib/paper_trail_diff/live_endpoint_batch_loader.rb', line 111 def targets(records, reflection) unique_records(records.flat_map do |record| Array(record.association(reflection.name).target) end) end |