lib/pbbuilder/template.rb in pbbuilder-0.12.0 vs lib/pbbuilder/template.rb in pbbuilder-0.13.0

- old
+ new

@@ -45,10 +45,105 @@ else super end end + # Caches fragment of message. Can be called like the following: + # 'pb.cache! "cache-key" do; end' + # 'pb.cache! "cache-key", expire_in: 1.min do; end' + # + # @param key String + # @param options Hash + # + # @return nil + def cache!(key=nil, options={}) + if @context.controller.perform_caching + value = _cache_fragment_for(key, options) do + _scope(target!) { yield self }.to_h.compact_blank + end + + merge! value + else + yield + end + end + + # Conditionally caches the protobuf message depending on the condition given as first parameter. Has the same + # signature as the `cache` helper method in `ActionView::Helpers::CacheHelper` and so can be used in + # the same way. + # + # Example: + # + # pb.cache_if! !admin?, @person, expires_in: 10.minutes do + # pb.extract! @person, :name, :age + # end + def cache_if!(condition, *args, &block) + condition ? cache!(*args, &block) : yield + end + private + + # Writes to cache, if cache with keys is missing. + # + # @return fragment value + + def _cache_fragment_for(key, options, &block) + key = _cache_key(key, options) + _read_fragment_cache(key, options) || _write_fragment_cache(key, options, &block) + end + + # Reads from cache + # + # @param key string + # @params options hash + # + # @return string + def _read_fragment_cache(key, options = nil) + @context.controller.instrument_fragment_cache :read_fragment, key do + ::Rails.cache.read(key, options) + end + end + + # Writes into cache and returns value + # + # @param key string + # @params options hash + # + # @return string + def _write_fragment_cache(key, options = nil) + @context.controller.instrument_fragment_cache :_write_fragment, key do + yield.tap do |value| + ::Rails.cache.write(key, value, options) + end + end + end + + # Composes full cache key for internal storage + # + # @param key string + # @param options hash + # + # @return string + def _cache_key(key, options) + name_options = options.slice(:skip_digest, :virtual_path) + key = _fragment_name_with_digest(key, name_options) + + if @context.respond_to?(:combined_fragment_cache_key) + key = @context.combined_fragment_cache_key(key) + else + key = url_for(key).split('://', 2).last if ::Hash === key + end + + ::ActiveSupport::Cache.expand_cache_key(key, :ppbuilder) + end + + def _fragment_name_with_digest(key, options) + if @context.respond_to?(:cache_fragment_name) + @context.cache_fragment_name(key, **options) + else + key + end + end def _is_active_model?(object) object.class.respond_to?(:model_name) && object.respond_to?(:to_partial_path) end