ruby-on-railsrubyrubygemsruby-on-rails-6jsonapi-serialize

How to customize jsonapi-serializer caching namespace - Ruby on Rails


In my rails application I have categories which are classified based on location. I want to cache these categories on serializer level by using jsonapi-serializer's caching method cache_options store: Rails.cache, namespace: 'jsonapi-serializer', expires_in: 3.hours. The issue here is that when I call it for the first time to retrieve categories in City A for example then later try to retrieve categories from City B it will still show City A's data. What I'm trying to do now is to pass city to serializer then add it to namespace using something like this namespace: "jsonapi-serializer/categories/#{:city}" in order to differentiate between them but I'm not able to find a way to do so yet.

Currently I have this block of code to retrieve categories based on location then serialize and render a json

      category = Category.active_categories(headers['User-Location'])

      unless category.empty?
        generic_category = Category.all_category
        categories = generic_category, category
        render CategorySerializer.new(categories.flatten, { params: { user_location: headers['User-Location'] } })
      end

While Category.active_categories and Category.all_category are caching the queries as below:

active_categories:

def self.active_categories(user_location)
  Rails.cache.fetch("active_categories/#{user_location}", expires_in: 3.hours) do
    Category.where(status: 'active')
            .joins(:sellers).where(sellers: { status: 'active', is_validated: true })
            .joins(sellers: :cities).where(cities: { name_en: user_location })
            .joins(sellers: :products).where(products: { status: 'available' })
            .where.not(products: { quantity: 0 }).with_attached_cover
            .order(featured: :desc).uniq.to_a
  end
end

all_category:

def self.all_category
Rails.cache.fetch('all_category', expires_in: 24.hours) do
  Category.where(name_en: 'All').with_attached_cover.first
  end
end

Solution

  • Found the solution already. Just override the caching method as the example below:

    require 'active_support/cache'
    
    class MySerializer
      include JSONAPI::Serializer
    
      cache_options(store: Rails.cache, namespace: 'jsonapi-serializer', expires_in: 3.hours)
    
      def self.record_cache_options(options, fieldset, include_list, params)
        return super(options, fieldset, include_list, params) if params[:user_location].blank?
        opts = options.dup
        opts[:namespace] += ':' + params[:user_location]
        opts
      end
    end