API low-level caching
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:
For the vehicle caching itself is there a better approach than my
vehicle = Vehicle.find_cached(params[:id])
. This is not usingupdated_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 likeRails.cache.fetch(["vehicles", vehicle], version: vehicle.updated_at)
as it is proposed here: https://github.com/rails/rails/pull/29092 since this needs thevehicle
instance. As you see theset_vehicle
controller method is pretty awkward.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]) end
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
end
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)
end
def self.find_cached(vehicle_id)
Rails.cache.fetch(['vehicles', vehicle_id]) { find(vehicle_id) }
end
end
vehicles_controller
before_action :set_vehicle, only: [:show]
def show
render json: VehicleSerializer.new(@vehicle, options).serialized_json
end
private
def set_vehicle
vehicle = Vehicle.find_cached(params[:id])
@vehicle = Rails.cache.fetch(['vehicles', vehicle, include_params], version: vehicle.updated_at) do
Vehicle.includes(include_params).find(params[:id])
end
authorize @vehicle
end
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)
vehicle.service_intervals
end
end