Class: WCC::Contentful::Model

Inherits:
Object
  • Object
show all
Extended by:
Helpers, ModelValidators, ServiceAccessors
Defined in:
lib/wcc/contentful/model.rb

Overview

This is the top layer of the WCC::Contentful gem. It exposes an API by which you can query for data from Contentful. The API is only accessible after calling WCC::Contentful.init!

The WCC::Contentful::Model class is the base class for all auto-generated model classes. A model class represents a content type inside Contentful. For example, the “page” content type is represented by a class named WCC::Contentful::Model::Page

This WCC::Contentful::Model::Page class exposes the following API methods:

The returned objects are instances of WCC::Contentful::Model::Page, or whatever constant exists in the registry for the page content type. You can register custom types to be instantiated for each content type. If a Model is subclassed, the subclass is automatically registered. This allows you to put models in your app’s ‘app/models` directory:

class Page < WCC::Contentful::Model::Page; end

and then use the API via those models:

# this returns a ::Page, not a WCC::Contentful::Model::Page
Page.find_by(slug: 'foo')

Furthermore, anytime links are automatically resolved, the registered classes will be used:

Menu.find_by(name: 'home').buttons.first.linked_page # is a ::Page

Direct Known Subclasses

DropdownMenu, Menu, MenuButton, Page, Redirect

Defined Under Namespace

Classes: DropdownMenu, Menu, MenuButton, Page, Redirect

Constant Summary collapse

@@registry =
{}

Constants included from ServiceAccessors

ServiceAccessors::SERVICES

Class Method Summary collapse

Methods included from Helpers

constant_from_content_type, content_type_from_constant, content_type_from_raw, shared_prefix

Methods included from ModelValidators

no_validate_field, schema, transform_content_types_for_validation, validate_field, validate_fields, validations

Class Method Details

.const_missing(name) ⇒ Object



50
51
52
53
# File 'lib/wcc/contentful/model.rb', line 50

def const_missing(name)
  raise WCC::Contentful::ContentTypeNotFoundError,
    "Content type '#{content_type_from_constant(name)}' does not exist in the space"
end

.find(id, context = nil) ⇒ Object

Finds an Entry or Asset by ID in the configured contentful space and returns an initialized instance of the appropriate model type.

Makes use of the configured store to access the Contentful CDN.



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

def self.find(id, context = nil)
  return unless raw = store.find(id)

  new_from_raw(raw, context)
end

.new_from_raw(raw, context = nil) ⇒ Object

Creates a new initialized instance of the appropriate model type for the given raw value. The raw value must be the same format as returned from one of the stores for a given object.



72
73
74
75
76
# File 'lib/wcc/contentful/model.rb', line 72

def self.new_from_raw(raw, context = nil)
  content_type = content_type_from_raw(raw)
  const = resolve_constant(content_type)
  const.new(raw, context)
end

.register_for_content_type(content_type = nil, klass: nil) ⇒ Object

Registers a class constant to be instantiated when resolving an instance of the given content type. This automatically happens for the first subclass of a generated model type, example:

class MyMenu < WCC::Contentful::Model::Menu
end

In the above case, instances of MyMenu will be instantiated whenever a ‘menu’ content type is resolved. The mapping can be made explicit with the optional parameters. Example:

class MyFoo < WCC::Contentful::Model::Foo
  register_for_content_type 'bar' # MyFoo is assumed
end

# in initializers/wcc_contentful.rb
WCC::Contentful::Model.register_for_content_type('bar', klass: MyFoo)

Raises:

  • (ArgumentError)


117
118
119
120
121
122
123
124
# File 'lib/wcc/contentful/model.rb', line 117

def self.register_for_content_type(content_type = nil, klass: nil)
  klass ||= self
  raise ArgumentError, "#{klass} must be a class constant!" unless klass.respond_to?(:new)

  content_type ||= content_type_from_constant(klass)

  @@registry[content_type] = klass
end

.registered?(content_type) ⇒ Boolean

Checks if a content type has already been registered to a class and returns that class. If nil, the generated WCC::Contentful::Model::content_type class will be resolved for this content type.

Returns:

  • (Boolean)


136
137
138
# File 'lib/wcc/contentful/model.rb', line 136

def self.registered?(content_type)
  @@registry[content_type]
end

.registryObject

Returns the current registry of content type names to constants.



127
128
129
130
131
# File 'lib/wcc/contentful/model.rb', line 127

def self.registry
  return {} unless @@registry

  @@registry.dup.freeze
end

.resolve_constant(content_type) ⇒ Object

Accepts a content type ID as a string and returns the Ruby constant stored in the registry that represents this content type.



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/wcc/contentful/model.rb', line 80

def self.resolve_constant(content_type)
  const = @@registry[content_type]
  return const if const

  const_name = constant_from_content_type(content_type).to_s
  begin
    # The app may have defined a model and we haven't loaded it yet
    const = Object.const_missing(const_name)
    return const if const && const < WCC::Contentful::Model
  rescue NameError => e
    raise e unless e.message =~ /uninitialized constant #{const_name}/

    nil
  end

  # Autoloading couldn't find their model - we'll register our own.
  const = WCC::Contentful::Model.const_get(constant_from_content_type(content_type))
  register_for_content_type(content_type, klass: const)
end