module AmsLazyRelationships::Core::LazyDigMethod
Provides `lazy_dig` as an instance method for serializers, in order to make possible to dig relationships in depth just like `Hash#dig` do, keeping the laziness and N+1-free evaluation.
Public Instance Methods
lazy_dig(*relation_names)
click to toggle source
@param relation_names [Array<Symbol>] the sequence of relation names
to dig through.
@return [ActiveRecord::Base, Array<ActiveRecord::Base>, nil] ActiveRecord
objects found by digging through the sequence of nested relationships. Singular or plural nature of returned value depends from the singular/plural nature of the chain of relation_names.
@example
class AuthorSerializer < BaseSerializer lazy_belongs_to :address lazy_has_many :rewards end class BlogPostSerializer < BaseSerializer lazy_belongs_to :author attribute :author_address do # returns single AR object or nil lazy_dig(:author, :address)&.full_address end attribute :author_rewards do # returns an array of AR objects lazy_dig(:author, :rewards).map(&:description) end end
# File lib/ams_lazy_relationships/core/lazy_dig_method.rb, line 34 def lazy_dig(*relation_names) relationships = { multiple: false, data: [{ serializer: self.class, object: object }] } relation_names.each do |relation_name| lazy_dig_relationship!(relation_name, relationships) end objects = relationships[:data].map { |r| r[:object] } relationships[:multiple] ? objects : objects.first end
Private Instance Methods
lazy_dig_next_objects!(relation_name, serializer, object)
click to toggle source
# File lib/ams_lazy_relationships/core/lazy_dig_method.rb, line 71 def lazy_dig_next_objects!(relation_name, serializer, object) serializer&.send( :load_lazy_relationship, relation_name, object ) end
lazy_dig_next_relationships!(relation_name, serializer, next_objects)
click to toggle source
# File lib/ams_lazy_relationships/core/lazy_dig_method.rb, line 79 def lazy_dig_next_relationships!(relation_name, serializer, next_objects) Array.wrap(next_objects).map do |next_object| next_serializer = serializer.send( :lazy_serializer_for, next_object, relation_name: relation_name ) { serializer: next_serializer, object: next_object } end end
lazy_dig_relationship!(relation_name, relationships)
click to toggle source
# File lib/ams_lazy_relationships/core/lazy_dig_method.rb, line 54 def lazy_dig_relationship!(relation_name, relationships) relationships[:data].map! do |data| serializer = data[:serializer] object = data[:object] next_objects = lazy_dig_next_objects!(relation_name, serializer, object) next unless next_objects relationships[:multiple] ||= next_objects.respond_to?(:to_ary) lazy_dig_next_relationships!(relation_name, serializer, next_objects) end relationships[:data].flatten! relationships[:data].compact! end