wcc-contentful 1.0.8 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,182 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/core_ext/module/introspection'
4
+
5
+ module WCC::Contentful::ModelAPI
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ include WCC::Contentful::Instrumentation
10
+
11
+ # override class-level _instrumentation from WCC::Contentful::Instrumentation
12
+ def self._instrumentation
13
+ services.instrumentation
14
+ end
15
+
16
+ # We use a class var here because this is a global registry for all subclasses
17
+ # of this namespace
18
+ @@registry = {} # rubocop:disable Style/ClassVars
19
+ end
20
+
21
+ class_methods do
22
+ attr_reader :configuration
23
+
24
+ def configure(configuration = nil, schema: nil, services: nil)
25
+ configuration ||= @configuration || WCC::Contentful::Configuration.new
26
+ yield(configuration) if block_given?
27
+
28
+ @schema = schema if schema
29
+ @services = services if services
30
+ @configuration = configuration.freeze
31
+
32
+ WCC::Contentful::ModelBuilder.new(self.schema, namespace: self).build_models
33
+ nil
34
+ end
35
+
36
+ def services
37
+ @services ||=
38
+ # try looking up the class heierarchy
39
+ (superclass.services if superclass.respond_to?(:services)) ||
40
+ # create it if we have a configuration
41
+ WCC::Contentful::Services.new(configuration)
42
+ end
43
+
44
+ def store(preview = nil)
45
+ ActiveSupport::Deprecation.warn('Use services.store instead')
46
+
47
+ preview ? services.preview_store : services.store
48
+ end
49
+
50
+ def schema
51
+ return @schema if @schema
52
+
53
+ file = configuration.schema_file
54
+ schema_json = JSON.parse(File.read(file))['contentTypes']
55
+ unless schema_json
56
+ raise ArgumentError, 'Please give either a JSON array of content types or file to load from'
57
+ end
58
+
59
+ @schema = WCC::Contentful::ContentTypeIndexer.from_json_schema(schema_json).types
60
+ end
61
+
62
+ # Finds an Entry or Asset by ID in the configured contentful space
63
+ # and returns an initialized instance of the appropriate model type.
64
+ #
65
+ # Makes use of the {WCC::Contentful::Services#store configured store}
66
+ # to access the Contentful CDN.
67
+ def find(id, options: nil)
68
+ options ||= {}
69
+ store = options[:preview] ? services.preview_store : services.store
70
+ raw =
71
+ _instrumentation.instrument 'find.model.contentful.wcc', id: id, options: options do
72
+ store.find(id, options.except(*WCC::Contentful::ModelMethods::MODEL_LAYER_CONTEXT_KEYS))
73
+ end
74
+
75
+ new_from_raw(raw, options) if raw.present?
76
+ end
77
+
78
+ # Creates a new initialized instance of the appropriate model type for the
79
+ # given raw value. The raw value must be the same format as returned from one
80
+ # of the stores for a given object.
81
+ def new_from_raw(raw, context = nil)
82
+ content_type = WCC::Contentful::Helpers.content_type_from_raw(raw)
83
+ const = resolve_constant(content_type)
84
+ const.new(raw, context)
85
+ end
86
+
87
+ # Accepts a content type ID as a string and returns the Ruby constant
88
+ # stored in the registry that represents this content type.
89
+ def resolve_constant(content_type)
90
+ raise ArgumentError, 'content_type cannot be nil' unless content_type
91
+
92
+ const = @@registry[content_type]
93
+ return const if const
94
+
95
+ const_name = WCC::Contentful::Helpers.constant_from_content_type(content_type).to_s
96
+ # #parent renamed to #module_parent in Rails 6
97
+ parent = try(:module_parent) || self.parent
98
+
99
+ loop do
100
+ begin
101
+ # The app may have defined a model and we haven't loaded it yet
102
+ const = parent.const_missing(const_name)
103
+ return const if const && const < self
104
+ rescue NameError => e
105
+ raise e unless e.message =~ /uninitialized constant (.+::)*#{const_name}$/
106
+ end
107
+
108
+ # const_missing only searches recursively up the module tree in a Rails
109
+ # context. If we're in a non-Rails app, we have to do that recursion ourselves.
110
+ # Keep looking upwards until we get to Object.
111
+ break if parent == Object
112
+
113
+ parent = parent.try(:module_parent) || parent.parent
114
+ end
115
+
116
+ # Autoloading couldn't find their model - we'll register our own.
117
+ const = const_get(
118
+ WCC::Contentful::Helpers.constant_from_content_type(content_type)
119
+ )
120
+ register_for_content_type(content_type, klass: const)
121
+ end
122
+
123
+ # Registers a class constant to be instantiated when resolving an instance
124
+ # of the given content type. This automatically happens for the first subclass
125
+ # of a generated model type, example:
126
+ #
127
+ # class MyMenu < WCC::Contentful::Model::Menu
128
+ # end
129
+ #
130
+ # In the above case, instances of MyMenu will be instantiated whenever a 'menu'
131
+ # content type is resolved.
132
+ # The mapping can be made explicit with the optional parameters. Example:
133
+ #
134
+ # class MyFoo < WCC::Contentful::Model::Foo
135
+ # register_for_content_type 'bar' # MyFoo is assumed
136
+ # end
137
+ #
138
+ # # in initializers/wcc_contentful.rb
139
+ # WCC::Contentful::Model.register_for_content_type('bar', klass: MyFoo)
140
+ def register_for_content_type(content_type = nil, klass: nil)
141
+ klass ||= self
142
+ raise ArgumentError, "#{klass} must be a class constant!" unless klass.respond_to?(:new)
143
+
144
+ content_type ||= WCC::Contentful::Helpers.content_type_from_constant(klass)
145
+
146
+ @@registry[content_type] = klass
147
+ end
148
+
149
+ # Returns the current registry of content type names to constants.
150
+ def registry
151
+ return {} unless @@registry
152
+
153
+ @@registry.dup.freeze
154
+ end
155
+
156
+ def reload!
157
+ registry = self.registry
158
+ registry.each do |(content_type, klass)|
159
+ const_name = klass.name
160
+ begin
161
+ # the const_name is fully qualified so search from root
162
+ const = Object.const_missing(const_name)
163
+ register_for_content_type(content_type, klass: const) if const
164
+ rescue NameError => e
165
+ msg = "Error when reloading constant #{const_name} - #{e}"
166
+ if defined?(Rails) && Rails.logger
167
+ Rails.logger.error msg
168
+ else
169
+ puts msg
170
+ end
171
+ end
172
+ end
173
+ end
174
+
175
+ # Checks if a content type has already been registered to a class and returns
176
+ # that class. If nil, the generated WCC::Contentful::Model::{content_type} class
177
+ # will be resolved for this content type.
178
+ def registered?(content_type)
179
+ @@registry[content_type]
180
+ end
181
+ end
182
+ end
@@ -7,8 +7,11 @@ module WCC::Contentful
7
7
  class ModelBuilder
8
8
  include Helpers
9
9
 
10
- def initialize(types)
10
+ attr_reader :namespace
11
+
12
+ def initialize(types, namespace: WCC::Contentful::Model)
11
13
  @types = types
14
+ @namespace = namespace
12
15
  end
13
16
 
14
17
  def build_models
@@ -21,12 +24,13 @@ module WCC::Contentful
21
24
 
22
25
  def build_model(typedef)
23
26
  const = typedef.name
24
- return WCC::Contentful::Model.const_get(const) if WCC::Contentful::Model.const_defined?(const)
27
+ ns = namespace
28
+ return ns.const_get(const) if ns.const_defined?(const)
25
29
 
26
30
  # TODO: https://github.com/dkubb/ice_nine ?
27
31
  typedef = typedef.deep_dup.freeze
28
- WCC::Contentful::Model.const_set(const,
29
- Class.new(WCC::Contentful::Model) do
32
+ ns.const_set(const,
33
+ Class.new(namespace) do
30
34
  extend ModelSingletonMethods
31
35
  include ModelMethods
32
36
  include Helpers
@@ -50,6 +54,8 @@ module WCC::Contentful
50
54
  typedef
51
55
  end
52
56
 
57
+ define_singleton_method(:model_namespace) { ns }
58
+
53
59
  define_method(:initialize) do |raw, context = nil|
54
60
  ct = content_type_from_raw(raw)
55
61
  if ct != typedef.content_type
@@ -5,8 +5,6 @@
5
5
  #
6
6
  # @api Model
7
7
  module WCC::Contentful::ModelMethods
8
- include WCC::Contentful::Instrumentation
9
-
10
8
  # The set of options keys that are specific to the Model layer and shouldn't
11
9
  # be passed down to the Store layer.
12
10
  MODEL_LAYER_CONTEXT_KEYS = %i[
@@ -40,6 +38,7 @@ module WCC::Contentful::ModelMethods
40
38
 
41
39
  typedef = self.class.content_type_definition
42
40
  links = fields.select { |f| %i[Asset Link].include?(typedef.fields[f].type) }
41
+ store = context[:preview] ? self.class.services.preview_store : self.class.services.store
43
42
 
44
43
  raw_link_ids =
45
44
  links.map { |field_name| raw.dig('fields', field_name, sys.locale) }
@@ -54,12 +53,11 @@ module WCC::Contentful::ModelMethods
54
53
  raw =
55
54
  _instrument 'resolve', id: id, depth: depth, backlinks: backlinked_ids do
56
55
  # use include param to do resolution
57
- self.class.store(context[:preview])
58
- .find_by(content_type: self.class.content_type,
59
- filter: { 'sys.id' => id },
60
- options: context.except(*MODEL_LAYER_CONTEXT_KEYS).merge!({
61
- include: [depth, 10].min
62
- }))
56
+ store.find_by(content_type: self.class.content_type,
57
+ filter: { 'sys.id' => id },
58
+ options: context.except(*MODEL_LAYER_CONTEXT_KEYS).merge!({
59
+ include: [depth, 10].min
60
+ }))
63
61
  end
64
62
  unless raw
65
63
  raise WCC::Contentful::ResolveError, "Cannot find #{self.class.content_type} with ID #{id}"
@@ -170,10 +168,10 @@ module WCC::Contentful::ModelMethods
170
168
  if raw.dig('sys', 'type') == 'Link'
171
169
  _instrument 'resolve',
172
170
  id: self.id, depth: depth, backlinks: context[:backlinks]&.map(&:id) do
173
- WCC::Contentful::Model.find(id, options: new_context)
171
+ self.class.model_namespace.find(id, options: new_context)
174
172
  end
175
173
  else
176
- WCC::Contentful::Model.new_from_raw(raw, new_context)
174
+ self.class.model_namespace.new_from_raw(raw, new_context)
177
175
  end
178
176
 
179
177
  m.resolve(depth: depth - 1, context: new_context, **options) if m && depth > 1
@@ -12,9 +12,9 @@ module WCC::Contentful::ModelSingletonMethods
12
12
  # WCC::Contentful::Model::Page.find(id)
13
13
  def find(id, options: nil)
14
14
  options ||= {}
15
- store = store(options[:preview])
15
+ store = options[:preview] ? services.preview_store : services.store
16
16
  raw =
17
- WCC::Contentful::Instrumentation.instrument 'find.model.contentful.wcc',
17
+ _instrumentation.instrument 'find.model.contentful.wcc',
18
18
  content_type: content_type, id: id, options: options do
19
19
  store.find(id, { hint: type }.merge!(options.except(:preview)))
20
20
  end
@@ -34,9 +34,9 @@ module WCC::Contentful::ModelSingletonMethods
34
34
 
35
35
  filter.transform_keys! { |k| k.to_s.camelize(:lower) } if filter.present?
36
36
 
37
- store = store(options[:preview])
37
+ store = options[:preview] ? services.preview_store : services.store
38
38
  query =
39
- WCC::Contentful::Instrumentation.instrument 'find_all.model.contentful.wcc',
39
+ _instrumentation.instrument 'find_all.model.contentful.wcc',
40
40
  content_type: content_type, filter: filter, options: options do
41
41
  store.find_all(content_type: content_type, options: options.except(:preview))
42
42
  end
@@ -56,9 +56,9 @@ module WCC::Contentful::ModelSingletonMethods
56
56
 
57
57
  filter.transform_keys! { |k| k.to_s.camelize(:lower) } if filter.present?
58
58
 
59
- store = store(options[:preview])
59
+ store = options[:preview] ? services.preview_store : services.store
60
60
  result =
61
- WCC::Contentful::Instrumentation.instrument 'find_by.model.contentful.wcc',
61
+ _instrumentation.instrument 'find_by.model.contentful.wcc',
62
62
  content_type: content_type, filter: filter, options: options do
63
63
  store.find_by(content_type: content_type, filter: filter, options: options.except(:preview))
64
64
  end
@@ -12,16 +12,18 @@ module WCC::Contentful::RSpec
12
12
  # Builds out a fake Contentful entry for the given content type, and then
13
13
  # stubs the Model API to return that content type for `.find` and `.find_by`
14
14
  # query methods.
15
- def contentful_stub(content_type, **attrs)
16
- const = WCC::Contentful::Model.resolve_constant(content_type.to_s)
17
- instance = contentful_create(content_type, **attrs)
15
+ def contentful_stub(const, **attrs)
16
+ unless const.respond_to?(:content_type_definition)
17
+ const = WCC::Contentful::Model.resolve_constant(const.to_s)
18
+ end
19
+ instance = contentful_create(const, **attrs)
18
20
 
19
21
  # mimic what's going on inside model_singleton_methods.rb
20
22
  # find, find_by, etc always return a new instance from the same raw
21
23
  allow(WCC::Contentful::Model).to receive(:find)
22
24
  .with(instance.id, any_args) do |_id, keyword_params|
23
25
  options = keyword_params && keyword_params[:options]
24
- contentful_create(content_type, options, raw: instance.raw, **attrs)
26
+ contentful_create(const, options, raw: instance.raw, **attrs)
25
27
  end
26
28
  allow(const).to receive(:find) { |id, options| WCC::Contentful::Model.find(id, **(options || {})) }
27
29
 
@@ -31,7 +33,7 @@ module WCC::Contentful::RSpec
31
33
  filter = filter&.dup
32
34
  options = filter&.delete(:options) || {}
33
35
 
34
- contentful_create(content_type, options, raw: instance.raw, **attrs)
36
+ contentful_create(const, options, raw: instance.raw, **attrs)
35
37
  end
36
38
  end
37
39
 
@@ -4,15 +4,16 @@ module WCC::Contentful
4
4
  class Services
5
5
  class << self
6
6
  def instance
7
- @singleton__instance__ ||= new # rubocop:disable Naming/MemoizedInstanceVariableName
7
+ @singleton__instance__ ||= # rubocop:disable Naming/MemoizedInstanceVariableName
8
+ (new(WCC::Contentful.configuration) if WCC::Contentful.configuration)
8
9
  end
9
10
  end
10
11
 
11
- def configuration
12
- @configuration ||= WCC::Contentful.configuration
13
- end
12
+ attr_reader :configuration
13
+
14
+ def initialize(configuration)
15
+ raise ArgumentError, 'Not yet configured!' unless configuration
14
16
 
15
- def initialize(configuration = nil)
16
17
  @configuration = configuration
17
18
  end
18
19
 
@@ -33,10 +34,7 @@ module WCC::Contentful
33
34
  #
34
35
  # @api Store
35
36
  def store
36
- @store ||=
37
- ensure_configured do |config|
38
- config.store.build(self)
39
- end
37
+ @store ||= configuration.store.build(self)
40
38
  end
41
39
 
42
40
  # An instance of {WCC::Contentful::Store::CDNAdapter} which connects to the
@@ -45,13 +43,11 @@ module WCC::Contentful
45
43
  # @api Store
46
44
  def preview_store
47
45
  @preview_store ||=
48
- ensure_configured do |config|
49
- WCC::Contentful::Store::Factory.new(
50
- config,
51
- :direct,
52
- :preview
53
- ).build(self)
54
- end
46
+ WCC::Contentful::Store::Factory.new(
47
+ configuration,
48
+ :direct,
49
+ :preview
50
+ ).build(self)
55
51
  end
56
52
 
57
53
  # Gets a {WCC::Contentful::SimpleClient::Cdn CDN Client} which provides
@@ -60,16 +56,15 @@ module WCC::Contentful
60
56
  # @api Client
61
57
  def client
62
58
  @client ||=
63
- ensure_configured do |config|
64
- WCC::Contentful::SimpleClient::Cdn.new(
65
- **config.connection_options,
66
- access_token: config.access_token,
67
- space: config.space,
68
- default_locale: config.default_locale,
69
- connection: config.connection,
70
- environment: config.environment
71
- )
72
- end
59
+ WCC::Contentful::SimpleClient::Cdn.new(
60
+ **configuration.connection_options,
61
+ access_token: configuration.access_token,
62
+ space: configuration.space,
63
+ default_locale: configuration.default_locale,
64
+ connection: configuration.connection,
65
+ environment: configuration.environment,
66
+ instrumentation: instrumentation
67
+ )
73
68
  end
74
69
 
75
70
  # Gets a {WCC::Contentful::SimpleClient::Cdn CDN Client} which provides
@@ -78,17 +73,16 @@ module WCC::Contentful
78
73
  # @api Client
79
74
  def preview_client
80
75
  @preview_client ||=
81
- ensure_configured do |config|
82
- if config.preview_token.present?
83
- WCC::Contentful::SimpleClient::Preview.new(
84
- **config.connection_options,
85
- preview_token: config.preview_token,
86
- space: config.space,
87
- default_locale: config.default_locale,
88
- connection: config.connection,
89
- environment: config.environment
90
- )
91
- end
76
+ if configuration.preview_token.present?
77
+ WCC::Contentful::SimpleClient::Preview.new(
78
+ **configuration.connection_options,
79
+ preview_token: configuration.preview_token,
80
+ space: configuration.space,
81
+ default_locale: configuration.default_locale,
82
+ connection: configuration.connection,
83
+ environment: configuration.environment,
84
+ instrumentation: instrumentation
85
+ )
92
86
  end
93
87
  end
94
88
 
@@ -98,17 +92,16 @@ module WCC::Contentful
98
92
  # @api Client
99
93
  def management_client
100
94
  @management_client ||=
101
- ensure_configured do |config|
102
- if config.management_token.present?
103
- WCC::Contentful::SimpleClient::Management.new(
104
- **config.connection_options,
105
- management_token: config.management_token,
106
- space: config.space,
107
- default_locale: config.default_locale,
108
- connection: config.connection,
109
- environment: config.environment
110
- )
111
- end
95
+ if configuration.management_token.present?
96
+ WCC::Contentful::SimpleClient::Management.new(
97
+ **configuration.connection_options,
98
+ management_token: configuration.management_token,
99
+ space: configuration.space,
100
+ default_locale: configuration.default_locale,
101
+ connection: configuration.connection,
102
+ environment: configuration.environment,
103
+ instrumentation: instrumentation
104
+ )
112
105
  end
113
106
  end
114
107
 
@@ -132,25 +125,30 @@ module WCC::Contentful
132
125
 
133
126
  # Gets the configured instrumentation adapter, defaulting to ActiveSupport::Notifications
134
127
  def instrumentation
135
- return @instrumentation if @instrumentation
136
- return ActiveSupport::Notifications if WCC::Contentful.configuration.nil?
137
-
138
128
  @instrumentation ||=
139
- WCC::Contentful.configuration.instrumentation_adapter ||
129
+ configuration.instrumentation_adapter ||
140
130
  ActiveSupport::Notifications
141
131
  end
142
-
143
- private
144
-
145
- def ensure_configured
146
- raise StandardError, 'WCC::Contentful has not yet been configured!' if configuration.nil?
147
-
148
- yield configuration
132
+ # Allow it to be injected into a store
133
+ alias_method :_instrumentation, :instrumentation
134
+
135
+ ##
136
+ # This method enables simple dependency injection -
137
+ # If the target has a setter matching the name of one of the services,
138
+ # set that setter with the value of the service.
139
+ def inject_into(target, except: [])
140
+ (WCC::Contentful::SERVICES - except).each do |s|
141
+ next unless target.respond_to?("#{s}=")
142
+
143
+ target.public_send("#{s}=",
144
+ public_send(s))
145
+ end
149
146
  end
150
147
  end
151
148
 
152
- SERVICES = (WCC::Contentful::Services.instance_methods -
153
- Object.instance_methods)
149
+ SERVICES =
150
+ WCC::Contentful::Services.instance_methods(false)
151
+ .select { |m| WCC::Contentful::Services.instance_method(m).arity == 0 }
154
152
 
155
153
  # Include this module to define accessors for every method defined on the
156
154
  # {Services} singleton.
@@ -158,7 +158,8 @@ module WCC::Contentful::Store
158
158
  def resolve_includes(entry, depth)
159
159
  return entry unless entry && depth && depth > 0
160
160
 
161
- WCC::Contentful::LinkVisitor.new(entry, :Link, :Asset, depth: depth - 1).map! do |val|
161
+ # Dig links out of response.includes and insert them into the entry
162
+ WCC::Contentful::LinkVisitor.new(entry, :Link, depth: depth - 1).map! do |val|
162
163
  resolve_link(val)
163
164
  end
164
165
  end
@@ -75,6 +75,7 @@ module WCC::Contentful::Store
75
75
  middleware, params, configure_proc = middleware_config
76
76
  middleware_options = options.merge((params || []).extract_options!)
77
77
  middleware = middleware.call(memo, *params, **middleware_options)
78
+ services.inject_into(middleware, except: %i[store preview_store])
78
79
  middleware&.instance_exec(&configure_proc) if configure_proc
79
80
  middleware || memo
80
81
  end
@@ -154,12 +155,7 @@ module WCC::Contentful::Store
154
155
  end
155
156
 
156
157
  # Inject services into the custom store class
157
- (WCC::Contentful::SERVICES - %i[store preview_store]).each do |s|
158
- next unless store.respond_to?("#{s}=")
159
-
160
- store.public_send("#{s}=",
161
- services.public_send(s))
162
- end
158
+ services.inject_into(store, except: %i[store preview_store])
163
159
 
164
160
  store
165
161
  end
@@ -108,7 +108,7 @@ module WCC::Contentful::Store
108
108
  includes = row.try(:includes) || row.try(:[], 1)
109
109
  return entry unless entry && depth && depth > 0
110
110
 
111
- WCC::Contentful::LinkVisitor.new(entry, :Link, :Asset,
111
+ WCC::Contentful::LinkVisitor.new(entry, :Link,
112
112
  # Walk all the links except for the leaf nodes
113
113
  depth: depth - 1).map! do |val|
114
114
  resolve_link(val, includes)
@@ -130,24 +130,6 @@ RSpec.shared_examples 'basic store' do
130
130
  JSON
131
131
  end
132
132
 
133
- before do
134
- allow(WCC::Contentful).to receive(:types)
135
- .and_return({
136
- 'root' => double(fields: {
137
- 'name' => double(name: 'name', type: :String, array: false),
138
- 'link' => double(name: 'link', type: :Link, array: false),
139
- 'links' => double(name: 'links', type: :Link, array: true)
140
- }),
141
- 'shallow' => double(fields: {
142
- 'name' => double(name: 'name', type: :String, array: false)
143
- }),
144
- 'deep' => double(fields: {
145
- 'name' => double(name: 'name', type: :String, array: false),
146
- 'subLink' => double(name: 'subLink', type: :Link, array: false)
147
- })
148
- })
149
- end
150
-
151
133
  describe '#set/#find' do
152
134
  describe 'ensures that the stored value is of type Hash' do
153
135
  it 'should not raise an error if value is a Hash' do
@@ -49,7 +49,6 @@ module WCC::Contentful
49
49
  end
50
50
 
51
51
  @store = store
52
- @state = read_state if should_sync?
53
52
  end
54
53
  if state
55
54
  @state = token_wrapper_factory(state)
@@ -31,10 +31,6 @@ module WCC::Contentful::Test::Attributes
31
31
  ##
32
32
  # Get a hash of default values for all attributes unique to the given Contentful model.
33
33
  def defaults(const)
34
- unless const < WCC::Contentful::Model
35
- raise ArgumentError, "#{const} is not a subclass of WCC::Contentful::Model"
36
- end
37
-
38
34
  const.content_type_definition.fields.each_with_object({}) do |(name, f), h|
39
35
  h[name.to_sym] = h[name.underscore.to_sym] = default_value(f)
40
36
  end
@@ -7,8 +7,10 @@ module WCC::Contentful::Test::Double
7
7
  # Builds a rspec double of the Contentful model for the given content_type.
8
8
  # All attributes that are known to be required fields on the content type
9
9
  # will return a default value based on the field type.
10
- def contentful_double(content_type, **attrs)
11
- const = WCC::Contentful::Model.resolve_constant(content_type)
10
+ def contentful_double(const, **attrs)
11
+ unless const.respond_to?(:content_type_definition)
12
+ const = WCC::Contentful::Model.resolve_constant(const.to_s)
13
+ end
12
14
  attrs.symbolize_keys!
13
15
 
14
16
  bad_attrs = attrs.reject { |a| const.instance_methods.include?(a) }
@@ -7,8 +7,10 @@ module WCC::Contentful::Test::Factory
7
7
  # Builds a in-memory instance of the Contentful model for the given content_type.
8
8
  # All attributes that are known to be required fields on the content type
9
9
  # will return a default value based on the field type.
10
- def contentful_create(content_type, context = nil, **attrs)
11
- const = WCC::Contentful::Model.resolve_constant(content_type.to_s)
10
+ def contentful_create(const, context = nil, **attrs)
11
+ unless const.respond_to?(:content_type_definition)
12
+ const = WCC::Contentful::Model.resolve_constant(const.to_s)
13
+ end
12
14
  attrs = attrs.transform_keys { |a| a.to_s.camelize(:lower) }
13
15
 
14
16
  id = attrs.delete('id')
@@ -2,6 +2,6 @@
2
2
 
3
3
  module WCC
4
4
  module Contentful
5
- VERSION = '1.0.8'
5
+ VERSION = '1.1.0'
6
6
  end
7
7
  end