Sha256: 37f417305b45286869d0bd6b385f96b0fc79b80fe840d96a4cfaa4bc5b4f9d34

Contents?: true

Size: 1.95 KB

Versions: 4

Compression:

Stored size: 1.95 KB

Contents

# frozen_string_literal: true

module AdequateSerialization
  module Rails
    class RelationSerializer
      attr_reader :relation

      def initialize(relation)
        @relation = relation
      end

      def as_json(*options)
        # Very purposefully using #length here. If you use #empty? or #count and
        # the relation isn't yet loaded, it's going to trigger another query.
        # Since we're going to need to map over each of the results in order to
        # serialize it anyway, it's better just to load it now and avoid the
        # extra query.
        return [] if relation.length.zero?

        opts = Options.from(*options, multi_caching: true)
        decorator = Decorator.from(opts.attachments)

        response_for(opts, decorator)
      end

      private

      def response_for(opts, decorator)
        cache_keys = cache_keys_for(opts)

        if cache_keys
          cacheable_response_for(opts, decorator, cache_keys)
        else
          uncacheable_response_for(opts, decorator)
        end
      end

      def cache_keys_for(opts)
        relation.map do |record|
          return nil unless CacheKey.cacheable?(record)

          CacheKey.for(record, opts.includes)
        end
      end

      def cacheable_response_for(opts, decorator, cache_keys)
        results =
          ::Rails.cache.fetch_multi(*cache_keys) do |(record, *)|
            serialize(record, opts)
          end

        cache_keys.map do |cache_key|
          decorator.decorate(results[cache_key])
        end
      end

      def uncacheable_response_for(opts, decorator)
        relation.map do |record|
          decorator.decorate(serialize(record, opts))
        end
      end

      def serialize(record, opts)
        record.class.serializer.serialize(record, opts)
      end
    end

    module RelationHook
      def as_json(*options)
        RelationSerializer.new(self).as_json(*options)
      end
    end

    ActiveRecord::Relation.include(RelationHook)
  end
end

Version data entries

4 entries across 4 versions & 1 rubygems

Version Path
adequate_serialization-2.0.1 lib/adequate_serialization/rails/relation_serializer.rb
adequate_serialization-2.0.0 lib/adequate_serialization/rails/relation_serializer.rb
adequate_serialization-1.0.1 lib/adequate_serialization/rails/relation_serializer.rb
adequate_serialization-1.0.0 lib/adequate_serialization/rails/relation_serializer.rb