module AmsLazyRelationships::Core::Evaluation
Module responsible for lazy loading the relationships during the runtime
Constants
- LAZY_NESTING_LEVELS
- NESTING_START_LEVEL
Private Instance Methods
deep_init_for_yielded_record(batch_record, lrm, level)
click to toggle source
# File lib/ams_lazy_relationships/core/evaluation.rb, line 77 def deep_init_for_yielded_record(batch_record, lrm, level) serializer = lazy_serializer_for(batch_record, lrm: lrm) return unless serializer serializer.send(:init_all_lazy_relationships, batch_record, level + 1) end
deep_init_for_yielded_records(batch_records, lrm, level)
click to toggle source
# File lib/ams_lazy_relationships/core/evaluation.rb, line 67 def deep_init_for_yielded_records(batch_records, lrm, level) # There'll be no more nesting if there's no # reflection for this relationship. We can skip deeper lazy loading. return unless lrm.reflection Array.wrap(batch_records).each do |r| deep_init_for_yielded_record(r, lrm, level) end end
init_all_lazy_relationships(object, level = NESTING_START_LEVEL)
click to toggle source
Recursively loads the tree of lazy relationships The nesting is limited to 3 levels.
@param object [Object] Lazy relationships will be loaded for this record. @param level [Integer] Current nesting level
# File lib/ams_lazy_relationships/core/evaluation.rb, line 37 def init_all_lazy_relationships(object, level = NESTING_START_LEVEL) return if level >= LAZY_NESTING_LEVELS return unless object return unless lazy_relationships lazy_relationships.each_value do |lrm| init_lazy_relationship(lrm, object, level) end end
init_lazy_relationship(lrm, object, level = NESTING_START_LEVEL)
click to toggle source
@param lrm [LazyRelationshipMeta] relationship data @param object [Object] Object to load the relationship for @param level [Integer] Current nesting level
# File lib/ams_lazy_relationships/core/evaluation.rb, line 51 def init_lazy_relationship(lrm, object, level = NESTING_START_LEVEL) load_for_object = if lrm.load_for.present? object.public_send(lrm.load_for) else object end lrm.loader.load(load_for_object) do |batch_records| deep_init_for_yielded_records( batch_records, lrm, level ) end end
lazy_serializer_for(object, lrm: nil, relation_name: nil)
click to toggle source
# File lib/ams_lazy_relationships/core/evaluation.rb, line 84 def lazy_serializer_for(object, lrm: nil, relation_name: nil) lrm ||= lazy_relationships[relation_name] return unless lrm&.reflection serializer_for(object, lrm.reflection.options) end
load_lazy_relationship(relation_name, object)
click to toggle source
Loads the lazy relationship
@param relation_name [Symbol] relation name to be loaded @param object [Object] Lazy relationships will be loaded for this record.
# File lib/ams_lazy_relationships/core/evaluation.rb, line 15 def load_lazy_relationship(relation_name, object) lrm = lazy_relationships[relation_name] unless lrm raise ArgumentError, "Undefined lazy '#{relation_name}' relationship for '#{name}' serializer" end # We need to evaluate the promise right before serializer tries # to touch it. Otherwise the various side effects can happen: # 1. AMS will attempt to serialize nil values with a specific V1 serializer # 2. `lazy_association ? 'exists' : 'missing'` expression will always # equal to 'exists' # 3. `lazy_association&.id` expression can raise NullPointer exception # # Calling `__sync` will evaluate the promise. init_lazy_relationship(lrm, object).__sync end