class WCC::Contentful::Store::Factory
This factory presents a DSL for configuring the store stack. The store stack sits in between the Model
layer and the datastore, which can be Contentful
or something else like Postgres.
A set of “presets” are available to get pre-configured stacks based on what we've found most useful.
Attributes
Set the base store instance.
Public Class Methods
# File lib/wcc/contentful/store/factory.rb, line 27 def initialize(config = WCC::Contentful.configuration, preset = :direct, options = nil) @config = config @preset = preset || :custom @options = [*options] || [] # Infer whether they passed in a store implementation object or class if class_implements_store_interface?(@preset) || object_implements_store_interface?(@preset) @options.unshift(@preset) @preset = :custom end configure_preset(@preset) end
Private Class Methods
The middleware that by default lives at the top of the middleware stack.
# File lib/wcc/contentful/store/factory.rb, line 179 def default_middleware [ [WCC::Contentful::Store::InstrumentationMiddleware] ].freeze end
Public Instance Methods
# File lib/wcc/contentful/store/factory.rb, line 64 def build(services = WCC::Contentful::Services.instance) store_instance = build_store(services) options = { config: config, services: services } middleware.reverse .reduce(store_instance) do |memo, middleware_config| # May have added a middleware with `middleware << MyMiddleware.new` middleware_config = [middleware_config] unless middleware_config.is_a? Array middleware, params, configure_proc = middleware_config middleware_options = options.merge((params || []).extract_options!) middleware = middleware.call(memo, *params, **middleware_options) middleware&.instance_exec(&configure_proc) if configure_proc middleware || memo end end
An array of tuples that set up and configure a Store
middleware.
# File lib/wcc/contentful/store/factory.rb, line 23 def middleware @middleware ||= self.class.default_middleware.dup end
# File lib/wcc/contentful/store/factory.rb, line 119 def preset_custom self.store = options.shift end
Configures the default “direct” preset which passes everything through to Contentful
CDN
# File lib/wcc/contentful/store/factory.rb, line 115 def preset_direct self.store = CDNAdapter.new(preview: options.include?(:preview)) end
Sets the “eager sync” preset using one of the preregistered stores like :postgres
# File lib/wcc/contentful/store/factory.rb, line 99 def preset_eager_sync store = options.shift || :memory store = SYNC_STORES[store]&.call(config, *options) if store.is_a?(Symbol) self.store = store end
Configures a “lazy sync” preset which caches direct lookups but hits Contentful
for any missing information. The cache is kept up to date by the sync engine.
# File lib/wcc/contentful/store/factory.rb, line 107 def preset_lazy_sync preset_direct use(WCC::Contentful::Middleware::Store::CachingMiddleware, ActiveSupport::Cache.lookup_store(*options)) end
# File lib/wcc/contentful/store/factory.rb, line 49 def replace(middleware, *middleware_params, &block) idx = self.middleware.find_index { |m| m[0] == middleware } raise ArgumentError, "Middleware #{middleware} not present" if idx.nil? configure_proc = block_given? ? Proc.new(&block) : nil self.middleware[idx] = [middleware, middleware_params, configure_proc] end
# File lib/wcc/contentful/store/factory.rb, line 57 def unuse(middleware) idx = self.middleware.find_index { |m| m[0] == middleware } return if idx.nil? self.middleware.delete_at idx end
Adds a middleware to the chain. Use a block here to configure the middleware after it has been created.
# File lib/wcc/contentful/store/factory.rb, line 44 def use(middleware, *middleware_params, &block) configure_proc = block_given? ? Proc.new(&block) : nil self.middleware << [middleware, middleware_params, configure_proc] end
# File lib/wcc/contentful/store/factory.rb, line 83 def validate! unless preset.nil? || PRESETS.include?(preset) raise ArgumentError, "Please use one of #{PRESETS} instead of #{preset}" end middleware.each do |m| next if m[0].respond_to?(:call) raise ArgumentError, "The middleware '#{m[0]&.try(:name) || m[0]}' cannot be applied! " \ 'It must respond to :call' end validate_store!(store) end
Private Instance Methods
# File lib/wcc/contentful/store/factory.rb, line 147 def build_store(services) store_class = store store = if object_implements_store_interface?(store_class) store_class else store_class.new(config, *options - [store_class]) end # Inject services into the custom store class (WCC::Contentful::SERVICES - %i[store preview_store]).each do |s| next unless store.respond_to?("#{s}=") store.public_send("#{s}=", services.public_send(s)) end store end
# File lib/wcc/contentful/store/factory.rb, line 167 def class_implements_store_interface?(klass) (WCC::Contentful::Store::Interface::INTERFACE_METHODS - (klass.try(:instance_methods) || [])).empty? end
# File lib/wcc/contentful/store/factory.rb, line 139 def configure_preset(preset) unless respond_to?("preset_#{preset}") raise ArgumentError, "Don't know how to build content delivery method '#{preset}'" end public_send("preset_#{preset}") end
# File lib/wcc/contentful/store/factory.rb, line 172 def object_implements_store_interface?(object) (WCC::Contentful::Store::Interface::INTERFACE_METHODS - (object.try(:methods) || [])).empty? end
# File lib/wcc/contentful/store/factory.rb, line 125 def validate_store!(store) raise ArgumentError, 'No store provided' unless store return true if class_implements_store_interface?(store) || object_implements_store_interface?(store) methods = [*store.try(:instance_methods), *store.try(:methods)] WCC::Contentful::Store::Interface::INTERFACE_METHODS.each do |method| next if methods.include?(method) raise ArgumentError, "Custom store '#{store}' must respond to the #{method} method" end end