Class: WCC::Contentful::Store::Factory

Inherits:
Object
  • Object
show all
Defined in:
lib/wcc/contentful/store/factory.rb

Overview

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.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config = WCC::Contentful.configuration, preset = :direct, options = nil) ⇒ Factory

Returns a new instance of Factory.



28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/wcc/contentful/store/factory.rb', line 28

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

Instance Attribute Details

#configObject (readonly)



18
19
20
# File 'lib/wcc/contentful/store/factory.rb', line 18

def config
  @config
end

#optionsObject (readonly)



18
19
20
# File 'lib/wcc/contentful/store/factory.rb', line 18

def options
  @options
end

#presetObject (readonly)



18
19
20
# File 'lib/wcc/contentful/store/factory.rb', line 18

def preset
  @preset
end

#storeObject

Set the base store instance.



21
22
23
# File 'lib/wcc/contentful/store/factory.rb', line 21

def store
  @store
end

Class Method Details

.default_middlewareObject

The middleware that by default lives at the top of the middleware stack.



180
181
182
183
184
185
186
# File 'lib/wcc/contentful/store/factory.rb', line 180

def default_middleware
  [
    [WCC::Contentful::Store::InstrumentationMiddleware],
    # Stores do not guarantee that the entry is resolved to the locale
    [WCC::Contentful::Middleware::Store::LocaleMiddleware]
  ].freeze
end

Instance Method Details

#build(services = WCC::Contentful::Services.instance) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/wcc/contentful/store/factory.rb', line 69

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)
      services.inject_into(middleware, except: %i[store preview_store])
      middleware&.instance_exec(&configure_proc) if configure_proc
      middleware || memo
    end
end

#middlewareObject

An array of tuples that set up and configure a Store middleware.



24
25
26
# File 'lib/wcc/contentful/store/factory.rb', line 24

def middleware
  @middleware ||= self.class.default_middleware.dup
end

#preset_customObject



125
126
127
# File 'lib/wcc/contentful/store/factory.rb', line 125

def preset_custom
  self.store = options.shift
end

#preset_directObject

Configures the default “direct” preset which passes everything through to Contentful CDN



121
122
123
# File 'lib/wcc/contentful/store/factory.rb', line 121

def preset_direct
  self.store = CDNAdapter.new(preview: options.include?(:preview))
end

#preset_eager_syncObject

Sets the “eager sync” preset using one of the preregistered stores like :postgres



105
106
107
108
109
# File 'lib/wcc/contentful/store/factory.rb', line 105

def preset_eager_sync
  store = options.shift || :memory
  store = SYNC_STORES[store]&.call(config, *options) if store.is_a?(Symbol)
  self.store = store
end

#preset_lazy_syncObject

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.



113
114
115
116
117
# File 'lib/wcc/contentful/store/factory.rb', line 113

def preset_lazy_sync
  preset_direct
  use(WCC::Contentful::Middleware::Store::CachingMiddleware,
    ActiveSupport::Cache.lookup_store(*options))
end

#replace(middleware, *middleware_params, &block) ⇒ Object

Replaces a middleware in the chain. The middleware to replace is selected by matching the class.

Raises:

  • (ArgumentError)


52
53
54
55
56
57
58
# File 'lib/wcc/contentful/store/factory.rb', line 52

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

#unuse(middleware) ⇒ Object

Removes a middleware from the chain, finding it by matching the class constant.



62
63
64
65
66
67
# File 'lib/wcc/contentful/store/factory.rb', line 62

def unuse(middleware)
  idx = self.middleware.find_index { |m| m[0] == middleware }
  return if idx.nil?

  self.middleware.delete_at idx
end

#use(middleware, *middleware_params, &block) ⇒ Object

Adds a middleware to the chain. Use a block here to configure the middleware after it has been created.



45
46
47
48
# File 'lib/wcc/contentful/store/factory.rb', line 45

def use(middleware, *middleware_params, &block)
  configure_proc = block_given? ? Proc.new(&block) : nil
  self.middleware << [middleware, middleware_params, configure_proc]
end

#validate!Object



89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/wcc/contentful/store/factory.rb', line 89

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