问题
I am a bit confused regarding Rails 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 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: https://github.com/rails/rails/pull/29092 since this needs the vehicle 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 is the correct way to handle caching here?
service_note.rb
setup same for service_interval.rb
and vehicle_alert.rb
class ServiceNote < ApplicationRecord
belongs_to :vehicle, touch: true
end
vehicle.rb
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.rb
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.rb (with fast_jsonapi gem)
# same for :service_notes and :vehicle_alerts
has_many :service_intervals do |vehicle, params|
if params[:include] && params[:include].include?(:service_intervals)
vehicle.service_intervals
end
end
来源:https://stackoverflow.com/questions/51689938/rails-5-api-low-level-caching