wcc-contentful 1.0.8 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c9a02a57e27811960957c32f2ee40cee58e7189f88ece1bdfd38353218c25d01
4
- data.tar.gz: '0364690883f6031f1d3258bd2284c4253e26854539536de9d32422f79632ce96'
3
+ metadata.gz: f99e076627c9facfff117f6d9df87dcf593d8a07bb6d3351b159172207aff81a
4
+ data.tar.gz: 463c6b34cbf4a5718736e04365a9705795fd1f3435167cc1028d5c217596fb34
5
5
  SHA512:
6
- metadata.gz: ac07e0be643d9880f86568b6ba4473d13ee3a7420771e859fee119ac0a021e8d630ed0e899f9ac4ed00b6759de655aab7fa59734185099d1240b59fef7160d45
7
- data.tar.gz: 777cc3dcb2f4e4cc22b8be485449151450f585e35477cef673f27569807ede4ec7bb418beed9dd39153fab8ad656a432fa565839e0e2775c4ffc69f981abb908
6
+ metadata.gz: 4be52c0f698f59b61f91d547ae7a2588b07bc9d184cd09a78730f7a09b290d005770b4f1ab3306d7e9cbc9ca0e5a20c7dc3c63fa39417a7c3219bf4c28ecd8a8
7
+ data.tar.gz: a1e93027a2a81655f9dbe82ee54c4f77061ef757c2dee9e3fe12369ce9f8d698fd01a7ab9a2510244273f567dbbdb05084eeb3b333abcafce9ccb05c6e62c4bc
data/README.md CHANGED
@@ -14,16 +14,20 @@ Table of Contents:
14
14
  2. [Installation](#installation)
15
15
  3. [Configuration](#configure)
16
16
  4. [Usage](#usage)
17
- 1. [Model API](#wcccontentfulmodel-api)
18
- 2. [Store API](#store-api)
19
- 3. [Direct CDN client](#direct-cdn-api-simpleclient)
20
- 4. [Accessing the APIs](#accessing-the-apis-within-application-code)
17
+ 1. [Model API](#wcccontentfulmodel-api)
18
+ 2. [Store API](#store-api)
19
+ 3. [Direct CDN client](#direct-cdn-api-simpleclient)
20
+ 4. [Accessing the APIs](#accessing-the-apis-within-application-code)
21
21
  5. [Architecture](#architecture)
22
+ 1. [Client Layer](#client-layer)
23
+ 2. [Store Layer](#store-layer)
24
+ 3. [Model Layer](#model-layer)
22
25
  6. [Test Helpers](#test-helpers)
23
26
  7. [Advanced Configuration Example](#advanced-configuration-example)
24
- 8. [Development](#development)
25
- 9. [Contributing](#contributing)
26
- 10. [License](#license)
27
+ 8. [Connecting to Multiple Spaces](#connecting-to-multiple-spaces-or-environments)
28
+ 9. [Development](#development)
29
+ 10. [Contributing](#contributing)
30
+ 11. [License](#license)
27
31
 
28
32
 
29
33
  ## Why did you rewrite the Contentful ruby stack?
@@ -45,7 +49,7 @@ The wcc-contentful gem enables caching at two levels: the HTTP response using [F
45
49
  By default, the contentful.rb gem requires the [HTTP library](https://rubygems.org/gems/http). While simple and straightforward to use, it is not as powerful for caching. We decided to make our client conform to the [Faraday gem's API](https://github.com/lostisland/faraday). If you prefer not to use Faraday, you can choose to supply your own HTTP adapter that "quacks like" Faraday (see the [TyphoeusAdapter](https://github.com/watermarkchurch/wcc-contentful/blob/master/wcc-contentful/lib/wcc/contentful/simple_client/typhoeus_adapter.rb) for one implementation).
46
50
 
47
51
  Using Faraday makes it easy to add Middleware. As an example, our flagship Rails app that powers watermark.org uses the following configuration in Production, which provides us with instrumentation through statsd, logging, and caching:
48
- ```rb
52
+ ```ruby
49
53
  config.connection = Faraday.new do |builder|
50
54
  builder.use :http_cache,
51
55
  shared_cache: false,
@@ -77,7 +81,7 @@ We also took advantage of Rails' naming conventions to automatically infer the c
77
81
 
78
82
  All our models are automatically generated at startup which improves response times at the expense of initialization time. In addition, our content model registry allows easy definition of custom models in your `app/models` directory to override fields. This plays nice with other gems like algoliasearch-rails, which allows you to declaratively manage your Algolia indexes. Another example from our flagship watermark.org:
79
83
 
80
- ```rb
84
+ ```ruby
81
85
  class Page < WCC::Contentful::Model::Page
82
86
  include AlgoliaSearch
83
87
 
@@ -327,6 +331,98 @@ end
327
331
 
328
332
  ![wcc-contentful diagram](./doc-static/wcc-contentful.png)
329
333
 
334
+ From the bottom up:
335
+
336
+ ### Client Layer
337
+
338
+ The {WCC::Contentful::SimpleClient} provides methods to access the [Contentful
339
+ Content Delivery API](https://www.contentful.com/developers/docs/references/content-delivery-api/)
340
+ through your favorite HTTP client gem. The SimpleClient expects
341
+ an Adapter that conforms to the Faraday interface.
342
+
343
+ Creating a SimpleClient to connect using different credentials, or to connect
344
+ without setting up all the rest of WCC::Contentful, is easy:
345
+
346
+ ```ruby
347
+ WCC::Contentful::SimpleClient::Cdn.new(
348
+ # required
349
+ access_token: 'xxxx',
350
+ space: '1234',
351
+ # optional
352
+ environment: 'staging', # omit to use master
353
+ default_locale: '*',
354
+ rate_limit_wait_timeout: 10,
355
+ instrumentation: ActiveSupport::Notifications,
356
+ connection: Faraday.new { |builder| ... },
357
+ )
358
+ ```
359
+
360
+ You can also create a {WCC::Contentful::SimpleClient::Preview} to talk to the
361
+ Preview API, or a {WCC::Contentful::SimpleClient::Management} to talk to the
362
+ Management API.
363
+
364
+ ### Store Layer
365
+
366
+ The Store Layer represents the data store where Contentful entries are kept for
367
+ querying. By default, `WCC::Contentful.init!` creates a {WCC::Contentful::Store::CDNAdapter}
368
+ which uses a {WCC::Contentful::SimpleClient::Cdn} instance to query entries from
369
+ the [Contentful Content Delivery API](https://www.contentful.com/developers/docs/references/content-delivery-api/). You can also query entries from another
370
+ source like Postgres or an in-memory hash if your data is small enough.
371
+
372
+ You can also implement your own store if you want! The gem contains a suite of
373
+ RSpec shared examples that give you a baseline for implementing your own store.
374
+ In your RSpec suite:
375
+ ```ruby
376
+ # frozen_string_literal: true
377
+
378
+ require 'my_store'
379
+ require 'wcc/contentful/store/rspec_examples'
380
+
381
+ RSpec.describe MyStore do
382
+ it_behaves_like 'contentful store', {
383
+ # Set which store features your store implements.
384
+ nested_queries: true, # Does your store implement JOINs?
385
+ include_param: true # Does your store resolve links when given the :include option?
386
+ }
387
+ ```
388
+
389
+ The store is kept up-to-date by the {WCC::Contentful::SyncEngine}. The `SyncEngine#next` methodcalls the `#index` method on the configured store in order to update
390
+ it with the latest data via the [Contentful Sync API](https://www.contentful.com/developers/docs/references/content-delivery-api/#/reference/synchronization). For example,
391
+ the {WCC::Contentful::Store::MemoryStore} uses this to update the hash with the
392
+ newest version of an entry, or delete an entry out of the hash.
393
+
394
+ #### Store Middleware
395
+
396
+ The store layer is made up of a base store (which implements {WCC::Contentful::Store::Interface}),
397
+ and optional middleware. The middleware
398
+ allows custom transformation of received entries via the `#select` and `#transform`
399
+ methods. To create your own middleware simply include {WCC::Contentful::Middleware::Store}
400
+ and implement those methods, then call `use` when configuring the store:
401
+
402
+ ```ruby
403
+ config.store :direct do
404
+ use MyMiddleware, param1: 'xxx'
405
+ end
406
+ ```
407
+
408
+ The most useful middleware is the {WCC::Contentful::Middleware::Store::CachingMiddleware},
409
+ which enables `:lazy_sync` mode (see {WCC::Contentful::Configuration#store})
410
+
411
+ ### Model Layer
412
+
413
+ This is the global top layer where your Rails app looks up content similarly to
414
+ ActiveModel. The models are namespaced under the root class {WCC::Contentful::Model}.
415
+ Each model's implementation of `.find`, `.find_by`, and `.find_all` simply call
416
+ into the configured Store.
417
+
418
+ The main benefit of the Model layer is lazy link resolution. When a model's
419
+ property is accessed, if that property is a link that has not been resolved
420
+ yet (for example using the `include: n` parameter on `.find_by`), the model
421
+ will automatically call `#find` on the store to resolve that linked entry.
422
+
423
+ Note that this can easily result in lots of CDN calls to Contentful! To optimize
424
+ this you should use the `include` parameter and/or use a different store.
425
+
330
426
  ## Test Helpers
331
427
 
332
428
  To use the test helpers, include the following in your rails_helper.rb:
@@ -460,6 +556,75 @@ rake wcc_contentful:download_schema
460
556
  All configuration options can be found [in the rubydoc](https://www.rubydoc.info/gems/wcc-contentful/WCC/Contentful/Configuration) under
461
557
  {WCC::Contentful::Configuration}
462
558
 
559
+ ## Connecting to multiple spaces or environments
560
+
561
+ When initializing the WCC::Contentful gem using `WCC::Contentful.init!`, the gem will by default connect to the single
562
+ Contentful space that you specify in the `WCC::Contentful.configure` step. However the gem is also capable of connecting
563
+ to multiple spaces within the same ruby process! You just have to create and initialize a namespace.
564
+
565
+ The {WCC::Contentful::ModelAPI} concern makes this straightforward. Start by creating your Namespace
566
+ and including the concern:
567
+ ```ruby
568
+ # app/models/my_second_space.rb
569
+ class MySecondSpace
570
+ include WCC::Contentful::ModelAPI
571
+ end
572
+
573
+ # app/models/other_page.rb
574
+ class OtherPage < MySecondSpace::Page
575
+ end
576
+ ```
577
+
578
+ Then configure it in an initializer:
579
+ ```ruby
580
+ # config/initializers/my_second_space.rb
581
+ MySecondSpace.configure do |config|
582
+ # Make sure to point to a different schema file from your first space!
583
+ config.schema_file = Rails.root.join('db/second-contentful-schema.json')
584
+
585
+ config.access_token = ENV['SECOND_CONTENTFUL_ACCESS_TOKEN']
586
+ config.preview_token = ENV['SECOND_CONTENTFUL_PREVIEW_ACCESS_TOKEN']
587
+ config.space = ENV['SECOND_CONTENTFUL_SPACE_ID']
588
+ config.environment = ENV['CONTENTFUL_ENVIRONMENT']
589
+ end
590
+ ```
591
+
592
+ Finally, use it:
593
+ ```ruby
594
+ OtherPage.find('1234')
595
+ # GET https://cdn.contentful.com/spaces/other-space/environments/other-env/entries/1234
596
+ # => #<OtherPage:0x0000000005c71a78 @created_at=2018-04-16 18:41:17 UTC...>
597
+
598
+ Page.find('1234')
599
+ # GET https://cdn.contentful.com/spaces/first-space/environments/first-env/entries/1234
600
+ # => #<Page:0x0000000001271b70 @created_at=2018-04-15 12:02:14 UTC...>
601
+ ```
602
+
603
+ The ModelAPI defines a second stack of services that you can access for lower level connections:
604
+ ```ruby
605
+ store = MySecondSpace.services.store
606
+ # => #<WCC::Contentful::Store::CDNAdapter:0x00007f888edac118
607
+ client = MySecondSpace.services.client
608
+ # => #<WCC::Contentful::SimpleClient::Cdn:0x00007f88942a8888
609
+ preview_client = MySecondSpace.services.preview_client
610
+ # => #<WCC::Contentful::SimpleClient::Preview:0x00007f888ccafa00
611
+ sync_engine = MySecondSpace.services.sync_engine
612
+ # => #<WCC::Contentful::SyncEngine:0x00007f88960b6b40
613
+ ```
614
+ Note that the above services are not accessible on {WCC::Contentful::Services.instance}
615
+ or via the {WCC::Contentful::ServiceAccessors}.
616
+
617
+ ### Using a sync store with a second space
618
+
619
+ If you use something other than the CDNAdapter with your second space, you will
620
+ need to find a way to trigger `MySecondSpace.services.sync_engine.next` to keep
621
+ it up-to-date. The {WCC::Contentful::Engine} will only manage the global SyncEngine
622
+ configured by the global {WCC::Contentful.configure}.
623
+
624
+ The easiest way to do this is to set up your own Rails route to respond to Contentful
625
+ webhooks and then configure the second Contentful space to send webhooks to this route.
626
+ You could also do this by triggering it periodically in a background job using
627
+ Sidekiq and [sidekiq-scheduler](https://github.com/Moove-it/sidekiq-scheduler).
463
628
 
464
629
  ## Development
465
630
 
@@ -11,13 +11,31 @@ module WCC::Contentful
11
11
  .name.parameterize.split('-').reverse.join('.')
12
12
  end
13
13
 
14
+ attr_writer :_instrumentation
15
+ def _instrumentation
16
+ # look for per-instance instrumentation then try class level
17
+ @_instrumentation || self.class._instrumentation
18
+ end
19
+
14
20
  included do
15
21
  protected
16
22
 
17
23
  def _instrument(name, payload = {}, &block)
18
24
  name += _instrumentation_event_prefix
19
- (@_instrumentation ||= WCC::Contentful::Services.instance.instrumentation)
20
- .instrument(name, payload, &block)
25
+ _instrumentation&.instrument(name, payload, &block)
26
+ end
27
+ end
28
+
29
+ class_methods do
30
+ attr_writer :_instrumentation
31
+
32
+ def _instrumentation
33
+ @_instrumentation ||
34
+ # try looking up the class heierarchy
35
+ superclass.try(:_instrumentation) ||
36
+ # default to global
37
+ WCC::Contentful::Services.instance&.instrumentation ||
38
+ ActiveSupport::Notifications
21
39
  end
22
40
  end
23
41
 
@@ -5,32 +5,21 @@
5
5
  # But you can use it too!
6
6
  class WCC::Contentful::LinkVisitor
7
7
  attr_reader :entry
8
- attr_reader :type
9
8
  attr_reader :fields
10
9
  attr_reader :depth
11
10
 
12
11
  # @param [Hash] entry The entry hash (resolved or unresolved) to walk
13
- # @param [Array<String, Symbol>] The fields to select from the entry tree.
14
- # Use `:Link` to select only links, or `'slug'` to select all slugs in the tree.
12
+ # @param [Array<Symbol>] The type of fields to select from the entry tree.
13
+ # Must be one of `:Link`, `:Entry`, `:Asset`.
15
14
  # @param [Fixnum] depth (optional) How far to walk down the tree of links. Be careful of
16
15
  # recursive trees!
17
- # @example
18
- # entry = store.find_by(id: id, include: 3)
19
- # WCC::Contentful::LinkVisitor.new(entry, 'slug', depth: 3)
20
- # .map { |slug| 'https://mirror-site' + slug }
21
16
  def initialize(entry, *fields, depth: 0)
22
- unless entry.is_a?(Hash) && entry.dig('sys', 'id')
17
+ unless entry.is_a?(Hash) && entry.dig('sys', 'type') == 'Entry'
23
18
  raise ArgumentError, "Please provide an entry as a hash value (got #{entry})"
24
19
  end
25
- unless ct = entry.dig('sys', 'contentType', 'sys', 'id')
26
- raise ArgumentError, 'Entry has no content type!'
27
- end
28
-
29
- @type = WCC::Contentful.types[ct]
30
- raise ArgumentError, "Unknown content type '#{ct}'" unless @type
31
20
 
32
21
  @entry = entry
33
- @fields = fields
22
+ @fields = fields.map(&:to_s)
34
23
  @depth = depth
35
24
  end
36
25
 
@@ -42,7 +31,7 @@ class WCC::Contentful::LinkVisitor
42
31
  # @returns nil
43
32
  def each(&block)
44
33
  _each do |val, field, locale, index|
45
- yield(val, field, locale, index) if should_yield_field?(field)
34
+ yield(val, field, locale, index) if should_yield_field?(field, val)
46
35
 
47
36
  next unless should_walk_link?(field, val)
48
37
 
@@ -54,7 +43,7 @@ class WCC::Contentful::LinkVisitor
54
43
 
55
44
  def map!(&block)
56
45
  _each do |val, field, locale, index|
57
- if should_yield_field?(field)
46
+ if should_yield_field?(field, val)
58
47
  val = yield(val, field, locale, index)
59
48
  set_field(field, locale, index, val)
60
49
  end
@@ -70,15 +59,15 @@ class WCC::Contentful::LinkVisitor
70
59
  private
71
60
 
72
61
  def _each(&block)
73
- type.fields.each_value do |f|
74
- each_field(f, &block)
62
+ (entry['fields'] || {}).each do |(k, _v)|
63
+ each_field(k, &block)
75
64
  end
76
65
  end
77
66
 
78
67
  def each_field(field)
79
68
  each_locale(field) do |val, locale|
80
- if field.array
81
- val&.each_with_index do |v, index|
69
+ if val&.is_a?(Array)
70
+ val.each_with_index do |v, index|
82
71
  yield(v, field, locale, index) unless v.nil?
83
72
  end
84
73
  else
@@ -88,7 +77,7 @@ class WCC::Contentful::LinkVisitor
88
77
  end
89
78
 
90
79
  def each_locale(field)
91
- raw_value = entry.dig('fields', field.name)
80
+ raw_value = entry.dig('fields', field)
92
81
  if locale = entry.dig('sys', 'locale')
93
82
  if raw_value.is_a?(Hash) && raw_value[locale]
94
83
  # it's a locale=* entry, but they've added sys.locale to those now
@@ -102,21 +91,28 @@ class WCC::Contentful::LinkVisitor
102
91
  end
103
92
  end
104
93
 
105
- def should_yield_field?(field)
106
- fields.empty? || fields.include?(field.type) || fields.include?(field.name)
94
+ def should_yield_field?(_field, value)
95
+ return true if fields.empty?
96
+
97
+ case value
98
+ when Hash
99
+ fields.include?(value.dig('sys', 'type'))
100
+ when Array
101
+ value.any? { |v| v.is_a?(Hash) && fields.include?(v.dig('sys', 'type')) }
102
+ end
107
103
  end
108
104
 
109
- def should_walk_link?(field, val, dep = depth)
110
- dep > 0 && field.type == :Link && val.dig('sys', 'type') == 'Entry'
105
+ def should_walk_link?(_field, val, dep = depth)
106
+ dep > 0 && val.is_a?(Hash) && val.dig('sys', 'type') == 'Entry'
111
107
  end
112
108
 
113
109
  def set_field(field, locale, index, val)
114
- current_field = (entry['fields'][field.name] ||= {})
110
+ current_field = (entry['fields'][field] ||= {})
115
111
 
116
- if field.array
117
- (current_field[locale] ||= [])[index] = val
118
- else
112
+ if index.nil?
119
113
  current_field[locale] = val
114
+ else
115
+ (current_field[locale] ||= [])[index] = val
120
116
  end
121
117
  end
122
118
  end
@@ -55,7 +55,8 @@ module WCC::Contentful::Middleware::Store
55
55
  def resolve_includes(entry, depth)
56
56
  return entry unless entry && depth && depth > 0
57
57
 
58
- WCC::Contentful::LinkVisitor.new(entry, :Link, depth: depth).map! do |val|
58
+ # We only care about entries (see #resolved_link?)
59
+ WCC::Contentful::LinkVisitor.new(entry, :Entry, depth: depth).map! do |val|
59
60
  resolve_link(val)
60
61
  end
61
62
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative './model_api'
4
+
3
5
  # This is the top layer of the WCC::Contentful gem. It exposes an API by which
4
6
  # you can query for data from Contentful. The API is only accessible after calling
5
7
  # WCC::Contentful.init!
@@ -37,137 +39,18 @@
37
39
  #
38
40
  # @api Model
39
41
  class WCC::Contentful::Model
40
- extend WCC::Contentful::Helpers
42
+ include WCC::Contentful::ModelAPI
41
43
 
42
44
  # The Model base class maintains a registry which is best expressed as a
43
45
  # class var.
44
46
  # rubocop:disable Style/ClassVars
45
47
 
46
48
  class << self
47
- include WCC::Contentful::ServiceAccessors
48
-
49
49
  def const_missing(name)
50
+ type = WCC::Contentful::Helpers.content_type_from_constant(name)
50
51
  raise WCC::Contentful::ContentTypeNotFoundError,
51
- "Content type '#{content_type_from_constant(name)}' does not exist in the space"
52
- end
53
- end
54
-
55
- @@registry = {}
56
-
57
- def self.store(preview = false)
58
- if preview
59
- if preview_store.nil?
60
- raise ArgumentError,
61
- 'You must include a contentful preview token in your WCC::Contentful.configure block'
62
- end
63
- preview_store
64
- else
65
- super()
66
- end
67
- end
68
-
69
- # Finds an Entry or Asset by ID in the configured contentful space
70
- # and returns an initialized instance of the appropriate model type.
71
- #
72
- # Makes use of the {WCC::Contentful::Services#store configured store}
73
- # to access the Contentful CDN.
74
- def self.find(id, options: nil)
75
- options ||= {}
76
- raw = store(options[:preview])
77
- .find(id, options.except(*WCC::Contentful::ModelMethods::MODEL_LAYER_CONTEXT_KEYS))
78
-
79
- new_from_raw(raw, options) if raw.present?
80
- end
81
-
82
- # Creates a new initialized instance of the appropriate model type for the
83
- # given raw value. The raw value must be the same format as returned from one
84
- # of the stores for a given object.
85
- def self.new_from_raw(raw, context = nil)
86
- content_type = content_type_from_raw(raw)
87
- const = resolve_constant(content_type)
88
- const.new(raw, context)
89
- end
90
-
91
- # Accepts a content type ID as a string and returns the Ruby constant
92
- # stored in the registry that represents this content type.
93
- def self.resolve_constant(content_type)
94
- raise ArgumentError, 'content_type cannot be nil' unless content_type
95
-
96
- const = @@registry[content_type]
97
- return const if const
98
-
99
- const_name = constant_from_content_type(content_type).to_s
100
- begin
101
- # The app may have defined a model and we haven't loaded it yet
102
- const = Object.const_missing(const_name)
103
- return const if const && const < WCC::Contentful::Model
104
- rescue NameError => e
105
- raise e unless e.message =~ /uninitialized constant #{const_name}/
106
-
107
- nil
52
+ "Content type '#{type}' does not exist in the space"
108
53
  end
109
-
110
- # Autoloading couldn't find their model - we'll register our own.
111
- const = WCC::Contentful::Model.const_get(constant_from_content_type(content_type))
112
- register_for_content_type(content_type, klass: const)
113
- end
114
-
115
- # Registers a class constant to be instantiated when resolving an instance
116
- # of the given content type. This automatically happens for the first subclass
117
- # of a generated model type, example:
118
- #
119
- # class MyMenu < WCC::Contentful::Model::Menu
120
- # end
121
- #
122
- # In the above case, instances of MyMenu will be instantiated whenever a 'menu'
123
- # content type is resolved.
124
- # The mapping can be made explicit with the optional parameters. Example:
125
- #
126
- # class MyFoo < WCC::Contentful::Model::Foo
127
- # register_for_content_type 'bar' # MyFoo is assumed
128
- # end
129
- #
130
- # # in initializers/wcc_contentful.rb
131
- # WCC::Contentful::Model.register_for_content_type('bar', klass: MyFoo)
132
- def self.register_for_content_type(content_type = nil, klass: nil)
133
- klass ||= self
134
- raise ArgumentError, "#{klass} must be a class constant!" unless klass.respond_to?(:new)
135
-
136
- content_type ||= content_type_from_constant(klass)
137
-
138
- @@registry[content_type] = klass
139
- end
140
-
141
- # Returns the current registry of content type names to constants.
142
- def self.registry
143
- return {} unless @@registry
144
-
145
- @@registry.dup.freeze
146
- end
147
-
148
- def self.reload!
149
- registry = self.registry
150
- registry.each do |(content_type, klass)|
151
- const_name = klass.name
152
- begin
153
- const = Object.const_missing(const_name)
154
- register_for_content_type(content_type, klass: const) if const
155
- rescue NameError => e
156
- msg = "Error when reloading constant #{const_name} - #{e}"
157
- if defined?(Rails) && Rails.logger
158
- Rails.logger.error msg
159
- else
160
- puts msg
161
- end
162
- end
163
- end
164
- end
165
-
166
- # Checks if a content type has already been registered to a class and returns
167
- # that class. If nil, the generated WCC::Contentful::Model::{content_type} class
168
- # will be resolved for this content type.
169
- def self.registered?(content_type)
170
- @@registry[content_type]
171
54
  end
172
55
  end
173
56