how to specify maximum_page_size config per resoruce in JR gem

35 Views Asked by At

So I have a rails application that use jsonapi-resources gem and in global config specified this config

JSONAPI.configure do |config|
  config.maximum_page_size = 1000
end

https://jsonapi-resources.com/v0.10/guide/basic_usage.html

But I want to use custom maximum_page_size in separate API resources for example /api/logs

module Api
  class LogResource < ApplicationResource
    immutable
    model_name 'Api::Log'
    primary_key :uuid

    def self.default_sort
      [{ field: 'time_start', direction: :desc }]
    end
  end
end

SO My question how to specify config only for this specific JSON API resource?

1

There are 1 best solutions below

0
engineersmnky On BEST ANSWER

From what I can determine in the source code maximum_page_size cannot be directly overridden at a resource level, so it appears the best way to handle this would be to implement a custom Paginator.

For your given example I think something as simple as the following should work:

class LimitedPageSizePaginator < PagedPaginator 
  MAX_PAGE_SIZE = 100 
  def initialize(params) 
    super
    verify_page_size_limit
  end 

  private 
    def verify_page_size_limit
      if @size > MAX_PAGE_SIZE
        fail JSONAPI::Exceptions::InvalidPageValue.new(:size, @size,
                detail: "size exceeds maximum page size of #{MAX_PAGE_SIZE}.")
      end
    end 
end 

Then you should be able to specify the Paginator for your resource

module Api
  class LogResource < ApplicationResource
    immutable
    model_name 'Api::Log'
    primary_key :uuid
   
    paginator :limited_page_size
    
    def self.default_sort
      [{ field: 'time_start', direction: :desc }]
    end
  end
end

If you need to make this more flexible e.g. not a fixed constant. Then we would need to create a method that dynamically creates a class on on the fly with the appropriate limitation set and then utilize that as the Paginator, something like.

module PaginatorCreator 
  class LimitedPaginator < PagedPaginator 
    class << self 
      attr_accessor :limit
      def paginator_name
        self.name.demodulize.underscore[..-11].to_sym
      end 
    end 

    def initialize(params) 
      super
      verify_page_size_limit
    end 

    private 
      def verify_page_size_limit
        if @size > self.class.limit
          fail JSONAPI::Exceptions::InvalidPageValue.new(:size, @size,
                  detail: "size exceeds maximum page size of #{self.class.limit}.")
        end
      end 
  end

  def self.create_limited_paginator(resource:,limit:) 
    klass = Object.const_set("#{resource.name.demodulize}LimitedPaginator",Class.new(LimitedPaginator)) 
    klass.limit = limit
    resource.paginator(klass.paginator_name)
  end 
end 

Then use as

class LogResource < ApplicationResource
    PaginatorCreator.create_limited_paginator(resource: self, limit: 100)
end  

Please Note: I have not used this library so there may be better solutions.