All threads / API low-level caching
Ask A Question


You’re not receiving notifications from this thread.

API low-level caching

Sean M asked in Ruby

Hey Chris,

I am a bit confused regarding API caching. I am using JSONAPI spec and fast_jsonapi gem and trying to cache the vehicle itself on show action and if there are params coming over like include=service_notes,service_alerts then I would like to cache those too. This is my initial approach but not sure if it is right.

I have 2 main issues:

  1. For the vehicle caching itself is there a better approach than my vehicle = Vehicle.find_cached(params[:id]). This is not using updated_at but an after save callback to update the cache if vehicle has been updated. I just don't see if I could somehow use sth like Rails.cache.fetch(["vehicles", vehicle], version: vehicle.updated_at) as it is proposed here: since this needs the vehicle instance. As you see the set_vehicle controller method is pretty awkward.

  2. Does this Rails.cache.fetch(['vehicles', vehicle, include_params], version: vehicle.updated_at) make any sense? I am trying to cache the query based on the different include params. Maybe it is overkill and I could just include everything and cache it that way like:

    Rails.cache.fetch(['vehicles', vehicle, 'with_includes'], version: vehicle.updated_at) do
        Vehicle.includes(:vehicle_alerts, :service_notes, :service_intervals).find(params[:id])

What do you think?

I hope you can help me out! Thanks in advance!

Code is below:

class ServiceNote < ApplicationRecord
    belongs_to :vehicle, touch: true

same with (ServiceAlert and ServiceInterval)

class Vehicle < ApplicationRecord
    after_save :update_cache
    has_many :vehicle_alerts, dependent: :delete_all
    has_many :service_notes, dependent: :delete_all
    has_many :service_intervals, dependent: :delete_all

    def update_cache
        Rails.cache.write(['vehicles', vehicle_id], self)

    def self.find_cached(vehicle_id)
        Rails.cache.fetch(['vehicles', vehicle_id]) { find(vehicle_id) }


before_action :set_vehicle, only: [:show]

def show
    render json:, options).serialized_json


def set_vehicle
    vehicle = Vehicle.find_cached(params[:id])

    @vehicle = Rails.cache.fetch(['vehicles', vehicle, include_params], version: vehicle.updated_at) do

    authorize @vehicle

vehicle_serializer (with fast_jsonapi gem), (same for vehicle_alerts and service_notes)

has_many :service_intervals do |vehicle, params|
    if params[:include] && params[:include].include?(:service_intervals)

I have the same question.

You could cache like this:

def method_name
return Rails.cache.fetch('method_name', :expires_in => 1.hours) {
# do something

Why not?
What is stopping you? :)

Join the discussion

Want to stay up-to-date with Ruby on Rails?

Join 68,326+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.

    logo Created with Sketch.

    Screencast tutorials to help you learn Ruby on Rails, Javascript, Hotwire, Turbo, Stimulus.js, PostgreSQL, MySQL, Ubuntu, and more. Icons by Icons8

    © 2022 GoRails, LLC. All rights reserved.