Caching Rendered Fragments
Type checking and key conversion run on every render. For data that is expensive to build and shared across requests, you can check it once and cache the result as a Camille::Rendered:
rendered = Camille::Types::Product.render!(serialize(product))
# => Camille::Rendered with the type's fingerprint and the final JSON string
Rails.cache.write("product/#{product.id}/#{Camille::Types::Product.new.fingerprint}", rendered)render! raises Camille::BasicType::RenderError if the value doesn't match the type. A Rendered can be placed anywhere a value of that type is expected:
render json: {
products: Rails.cache.read_multi(*keys).values # Product[]
}The type accepts it by comparing fingerprints instead of re-checking, and to_json splices the stored string verbatim, so no parsing or re-serialization happens on the cached fragments.
TIP
A Rendered is immutable and opaque. If a fragment needs to be modified before rendering, cache the plain hash instead and let Camille check it as usual; the two forms are a per-fragment choice.
Keep volatile or per-user fields outside cached fragments, and include the type's fingerprint in the cache key so entries are invalidated when the type changes.
Serialization
Rendered defines marshal_dump/marshal_load as [fingerprint, json], so the default Rails.cache coder stores just the two strings. If you use the :message_pack cache serializer, register the class with ActiveSupport::MessagePack::CacheSerializer using the same pair.