wcc-contentful 0.2.2 → 0.3.0.pre.rc
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rspec +0 -1
- data/README.md +181 -8
- data/app/controllers/wcc/contentful/webhook_controller.rb +42 -2
- data/app/jobs/wcc/contentful/delayed_sync_job.rb +52 -3
- data/app/jobs/wcc/contentful/webhook_enable_job.rb +43 -0
- data/bin/console +4 -3
- data/bin/rails +2 -0
- data/config/initializers/mime_types.rb +10 -1
- data/lib/wcc/contentful.rb +14 -142
- data/lib/wcc/contentful/client_ext.rb +17 -4
- data/lib/wcc/contentful/configuration.rb +25 -84
- data/lib/wcc/contentful/engine.rb +19 -0
- data/lib/wcc/contentful/exceptions.rb +25 -28
- data/lib/wcc/contentful/graphql.rb +0 -1
- data/lib/wcc/contentful/graphql/types.rb +1 -1
- data/lib/wcc/contentful/helpers.rb +3 -2
- data/lib/wcc/contentful/indexed_representation.rb +6 -0
- data/lib/wcc/contentful/model.rb +68 -34
- data/lib/wcc/contentful/model_builder.rb +65 -67
- data/lib/wcc/contentful/model_methods.rb +189 -0
- data/lib/wcc/contentful/model_singleton_methods.rb +83 -0
- data/lib/wcc/contentful/services.rb +146 -0
- data/lib/wcc/contentful/simple_client.rb +35 -33
- data/lib/wcc/contentful/simple_client/http_adapter.rb +9 -0
- data/lib/wcc/contentful/simple_client/management.rb +81 -0
- data/lib/wcc/contentful/simple_client/response.rb +61 -37
- data/lib/wcc/contentful/simple_client/typhoeus_adapter.rb +12 -0
- data/lib/wcc/contentful/store.rb +45 -18
- data/lib/wcc/contentful/store/base.rb +128 -8
- data/lib/wcc/contentful/store/cdn_adapter.rb +92 -22
- data/lib/wcc/contentful/store/lazy_cache_store.rb +94 -9
- data/lib/wcc/contentful/store/memory_store.rb +13 -8
- data/lib/wcc/contentful/store/postgres_store.rb +44 -11
- data/lib/wcc/contentful/sys.rb +28 -0
- data/lib/wcc/contentful/version.rb +1 -1
- data/wcc-contentful.gemspec +3 -9
- metadata +87 -107
- data/.circleci/config.yml +0 -51
- data/.gitignore +0 -26
- data/.rubocop.yml +0 -243
- data/.rubocop_todo.yml +0 -13
- data/.travis.yml +0 -5
- data/CHANGELOG.md +0 -45
- data/CODE_OF_CONDUCT.md +0 -74
- data/Guardfile +0 -58
- data/LICENSE.txt +0 -21
- data/Rakefile +0 -8
- data/lib/generators/wcc/USAGE +0 -24
- data/lib/generators/wcc/model_generator.rb +0 -90
- data/lib/generators/wcc/templates/.keep +0 -0
- data/lib/generators/wcc/templates/Procfile +0 -3
- data/lib/generators/wcc/templates/contentful_shell_wrapper +0 -385
- data/lib/generators/wcc/templates/menu/generated_add_menus.ts +0 -90
- data/lib/generators/wcc/templates/menu/models/menu.rb +0 -23
- data/lib/generators/wcc/templates/menu/models/menu_button.rb +0 -23
- data/lib/generators/wcc/templates/page/generated_add_pages.ts +0 -50
- data/lib/generators/wcc/templates/page/models/page.rb +0 -23
- data/lib/generators/wcc/templates/release +0 -9
- data/lib/generators/wcc/templates/wcc_contentful.rb +0 -17
- data/lib/wcc/contentful/model/menu.rb +0 -7
- data/lib/wcc/contentful/model/menu_button.rb +0 -15
- data/lib/wcc/contentful/model/page.rb +0 -8
- data/lib/wcc/contentful/model/redirect.rb +0 -19
- data/lib/wcc/contentful/model_validators.rb +0 -115
- data/lib/wcc/contentful/model_validators/dsl.rb +0 -165
@@ -1,90 +0,0 @@
|
|
1
|
-
|
2
|
-
import Migration from 'contentful-migration-cli'
|
3
|
-
|
4
|
-
export = function (migration: Migration) {
|
5
|
-
const menu = migration.createContentType('menu')
|
6
|
-
.name('Menu')
|
7
|
-
.description('A Menu contains a number of Menu Buttons or other Menus, which ' +
|
8
|
-
'will be rendered as drop-downs.')
|
9
|
-
.displayField('name')
|
10
|
-
|
11
|
-
menu.createField('name')
|
12
|
-
.name('Menu Name')
|
13
|
-
.type('Symbol')
|
14
|
-
.required(true)
|
15
|
-
|
16
|
-
menu.createField('topButton')
|
17
|
-
.name('Top Button')
|
18
|
-
.type('Link')
|
19
|
-
.linkType('Entry')
|
20
|
-
.validations([
|
21
|
-
{
|
22
|
-
linkContentType: [ 'menuButton' ],
|
23
|
-
message: 'The Top Button must be a button linking to a URL or page. ' +
|
24
|
-
'If the menu is a dropdown, this button is visible when it is collapsed.'
|
25
|
-
}
|
26
|
-
])
|
27
|
-
|
28
|
-
menu.createField('items')
|
29
|
-
.name('Items')
|
30
|
-
.type('Array')
|
31
|
-
.items({
|
32
|
-
type: 'Link',
|
33
|
-
linkType: 'Entry',
|
34
|
-
validations: [
|
35
|
-
{
|
36
|
-
linkContentType: [ 'menu', 'menuButton' ],
|
37
|
-
message: 'The items must be either buttons or drop-down menus'
|
38
|
-
}
|
39
|
-
]
|
40
|
-
})
|
41
|
-
|
42
|
-
const menuButton = migration.createContentType('menuButton')
|
43
|
-
.name('Menu Button')
|
44
|
-
.description('A Menu Button is a clickable button that goes on a Menu. ' +
|
45
|
-
'It has a link to a Page or a URL.')
|
46
|
-
.displayField('text')
|
47
|
-
|
48
|
-
menuButton.createField('text')
|
49
|
-
.name('Text')
|
50
|
-
.type('Symbol')
|
51
|
-
.required(true)
|
52
|
-
.validations([
|
53
|
-
{
|
54
|
-
size: { min: 1, max: 60 },
|
55
|
-
message: 'A Menu Button should have a very short text field - ideally a ' +
|
56
|
-
'single word. Please limit the text to 60 characters.'
|
57
|
-
}
|
58
|
-
])
|
59
|
-
|
60
|
-
menuButton.createField('icon')
|
61
|
-
.name('Icon')
|
62
|
-
.type('Link')
|
63
|
-
.linkType('Asset')
|
64
|
-
.validations([
|
65
|
-
{
|
66
|
-
linkMimetypeGroup: ['image']
|
67
|
-
}
|
68
|
-
])
|
69
|
-
|
70
|
-
menuButton.createField('externalLink')
|
71
|
-
.name('External Link')
|
72
|
-
.type('Symbol')
|
73
|
-
.validations([
|
74
|
-
{
|
75
|
-
regexp: { pattern: "^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$" },
|
76
|
-
message: "The external link must be a URL like 'https://www.watermark.org/'"
|
77
|
-
}
|
78
|
-
])
|
79
|
-
|
80
|
-
menuButton.createField('link')
|
81
|
-
.name('Page Link')
|
82
|
-
.type('Link')
|
83
|
-
.linkType('Entry')
|
84
|
-
.validations([
|
85
|
-
{
|
86
|
-
linkContentType: [ 'page' ],
|
87
|
-
message: 'The Page Link must be a link to a Page which has a slug.'
|
88
|
-
}
|
89
|
-
])
|
90
|
-
}
|
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# This model represents the 'menu' content type in Contentful. Any linked
|
4
|
-
# entries of the 'menu' content type will be resolved as instances of this class.
|
5
|
-
# It exposes #find, #find_by, and #find_all methods to query Contentful.
|
6
|
-
class Menu < WCC::Contentful::Model::Menu
|
7
|
-
# Add custom validations to ensure that app-specific properties exist:
|
8
|
-
# validate_field :foo, :String, :required
|
9
|
-
# validate_field :bar_links, :Array, link_to: %w[bar baz]
|
10
|
-
|
11
|
-
# Override functionality or add utilities
|
12
|
-
#
|
13
|
-
# # Example: override equality
|
14
|
-
# def ===(other)
|
15
|
-
# ...
|
16
|
-
# end
|
17
|
-
#
|
18
|
-
# # Example: override "name" attribute to always be camelized.
|
19
|
-
# # `@name` is populated by the gem in the initializer.
|
20
|
-
# def name
|
21
|
-
# @name_camelized ||= @name.camelize(true)
|
22
|
-
# end
|
23
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# This model represents the 'menuButton' content type in Contentful. Any linked
|
4
|
-
# entries of the 'menuButton' content type will be resolved as instances of this class.
|
5
|
-
# It exposes #find, #find_by, and #find_all methods to query Contentful.
|
6
|
-
class MenuButton < WCC::Contentful::Model::MenuButton
|
7
|
-
# Add custom validations to ensure that app-specific properties exist:
|
8
|
-
# validate_field :foo, :String, :required
|
9
|
-
# validate_field :bar_links, :Array, link_to: %w[bar baz]
|
10
|
-
|
11
|
-
# Override functionality or add utilities
|
12
|
-
#
|
13
|
-
# # Example: override equality
|
14
|
-
# def ===(other)
|
15
|
-
# ...
|
16
|
-
# end
|
17
|
-
#
|
18
|
-
# # Example: override "text" attribute to always be camelized.
|
19
|
-
# # `@text` is populated by the gem in the initializer.
|
20
|
-
# def text
|
21
|
-
# @text_camelized ||= @text.camelize(true)
|
22
|
-
# end
|
23
|
-
end
|
@@ -1,50 +0,0 @@
|
|
1
|
-
import Migration from 'contentful-migration-cli'
|
2
|
-
|
3
|
-
export = function (migration: Migration) {
|
4
|
-
const page = migration.createContentType('page')
|
5
|
-
.name('Page')
|
6
|
-
.description('A page describes a collection of sections that correspond' +
|
7
|
-
'to a URL slug')
|
8
|
-
.displayField('title')
|
9
|
-
|
10
|
-
page.createField('title')
|
11
|
-
.name('Title')
|
12
|
-
.type('Symbol')
|
13
|
-
.required(true)
|
14
|
-
|
15
|
-
page.createField('slug')
|
16
|
-
.name('Slug')
|
17
|
-
.type('Symbol')
|
18
|
-
.required(true)
|
19
|
-
.validations([
|
20
|
-
{
|
21
|
-
unique: true
|
22
|
-
},
|
23
|
-
{
|
24
|
-
regexp: { pattern: "(\\/|\\/([\w#!:.?+=&%@!\\-\\/]))?$" },
|
25
|
-
message: "The slug must look like the path part of a URL and begin with a forward slash, example: '/my-page-slug'"
|
26
|
-
}
|
27
|
-
])
|
28
|
-
|
29
|
-
page.createField('sections')
|
30
|
-
.name('Sections')
|
31
|
-
.type('Array')
|
32
|
-
.items({
|
33
|
-
type: 'Link',
|
34
|
-
linkType: 'Entry'
|
35
|
-
})
|
36
|
-
|
37
|
-
page.createField('subpages')
|
38
|
-
.name('Subpages')
|
39
|
-
.type('Array')
|
40
|
-
.items({
|
41
|
-
type: 'Link',
|
42
|
-
linkType: 'Entry',
|
43
|
-
validations: [
|
44
|
-
{
|
45
|
-
linkContentType: [ 'page' ]
|
46
|
-
}
|
47
|
-
]
|
48
|
-
})
|
49
|
-
|
50
|
-
}
|
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# This model represents the 'page' content type in Contentful. Any linked
|
4
|
-
# entries of the 'page' content type will be resolved as instances of this class.
|
5
|
-
# It exposes #find, #find_by, and #find_all methods to query Contentful.
|
6
|
-
class Page < WCC::Contentful::Model::Page
|
7
|
-
# Add custom validations to ensure that app-specific properties exist:
|
8
|
-
# validate_field :foo, :String, :required
|
9
|
-
# validate_field :bar_links, :Array, link_to: %w[bar baz]
|
10
|
-
|
11
|
-
# Override functionality or add utilities
|
12
|
-
#
|
13
|
-
# # Example: override equality
|
14
|
-
# def ===(other)
|
15
|
-
# ...
|
16
|
-
# end
|
17
|
-
#
|
18
|
-
# # Example: override "title" attribute to always be titlecase.
|
19
|
-
# # `@title` is populated by the gem in the initializer.
|
20
|
-
# def title
|
21
|
-
# @title_titlecased ||= @title.titlecase
|
22
|
-
# end
|
23
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
|
2
|
-
WCC::Contentful.configure do |config|
|
3
|
-
# Required
|
4
|
-
config.access_token = # Contentful CDN access token
|
5
|
-
config.space = # Contentful Space ID
|
6
|
-
|
7
|
-
# Optional
|
8
|
-
config.management_token = # Contentful API management token
|
9
|
-
config.default_locale = # Set default locale, if left blank this is 'en-US'
|
10
|
-
config.content_delivery = # :direct, :eager_sync, or :lazy_sync
|
11
|
-
end
|
12
|
-
|
13
|
-
# Download content types, build models, and sync content
|
14
|
-
WCC::Contentful.init!
|
15
|
-
|
16
|
-
# Validate that models conform to a defined specification
|
17
|
-
WCC::Contentful.validate_models! unless defined?(Rails) && Rails.env.development?
|
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class WCC::Contentful::Model::MenuButton < WCC::Contentful::Model
|
4
|
-
validate_field :text, :String, :required
|
5
|
-
validate_field :icon, :Asset, :optional
|
6
|
-
validate_field :external_link, :String, :optional
|
7
|
-
validate_field :link, :Link, :optional, link_to: 'page'
|
8
|
-
|
9
|
-
# Gets either the external link or the slug from the referenced page.
|
10
|
-
# Example usage: `<%= link_to button.title, button.href %>`
|
11
|
-
def href
|
12
|
-
return external_link if external_link
|
13
|
-
link&.try(:slug) || link&.try(:url)
|
14
|
-
end
|
15
|
-
end
|
@@ -1,8 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class WCC::Contentful::Model::Page < WCC::Contentful::Model
|
4
|
-
validate_field :title, :String
|
5
|
-
validate_field :slug, :String
|
6
|
-
validate_field :subpages, :Array, link_to: %w[page]
|
7
|
-
validate_field :sections, :Array, link_to: /^section/
|
8
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class WCC::Contentful::Model::Redirect < WCC::Contentful::Model
|
4
|
-
def href
|
5
|
-
if !url.nil?
|
6
|
-
url
|
7
|
-
elsif valid_page_reference?(pageReference)
|
8
|
-
"/#{pageReference.url}"
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
def valid_page_reference?(page_ref)
|
13
|
-
if !page_ref.nil? && !defined?(page_ref.url).nil?
|
14
|
-
true
|
15
|
-
else
|
16
|
-
false
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
@@ -1,115 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'dry-validation'
|
4
|
-
|
5
|
-
require_relative 'model_validators/dsl'
|
6
|
-
|
7
|
-
module WCC::Contentful::ModelValidators
|
8
|
-
def schema
|
9
|
-
return if validations.nil? || validations.empty?
|
10
|
-
|
11
|
-
all_field_validations =
|
12
|
-
validations.each_with_object({}) do |(content_type, procs), h|
|
13
|
-
next if procs.empty?
|
14
|
-
|
15
|
-
# "page": {
|
16
|
-
# "sys": { ... }
|
17
|
-
# "fields": {
|
18
|
-
# "title": { ... },
|
19
|
-
# "sections": { ... },
|
20
|
-
# ...
|
21
|
-
# }
|
22
|
-
# }
|
23
|
-
h[content_type] =
|
24
|
-
Dry::Validation.Schema do
|
25
|
-
# Had to dig through the internals of Dry::Validation to find
|
26
|
-
# this magic incantation
|
27
|
-
procs.each { |dsl| instance_eval(&dsl.to_proc) }
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
Dry::Validation.Schema do
|
32
|
-
all_field_validations.each do |content_type, fields_schema|
|
33
|
-
required(content_type).schema do
|
34
|
-
required('fields').schema(fields_schema)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def validations
|
41
|
-
# This needs to be a class variable so that subclasses defined in application
|
42
|
-
# code can add to the total package of model validations
|
43
|
-
# rubocop:disable Style/ClassVars
|
44
|
-
@@validations ||= {}
|
45
|
-
# rubocop:enable Style/ClassVars
|
46
|
-
end
|
47
|
-
|
48
|
-
##
|
49
|
-
# Accepts a block which uses the {dry-validation DSL}[http://dry-rb.org/gems/dry-validation/]
|
50
|
-
# to validate the 'fields' object of a content type.
|
51
|
-
def validate_fields(&block)
|
52
|
-
raise ArgumentError, 'validate_fields requires a block' unless block_given?
|
53
|
-
dsl = ProcDsl.new(Proc.new(&block))
|
54
|
-
|
55
|
-
ct = try(:content_type) || name.demodulize.camelize(:lower)
|
56
|
-
(validations[ct] ||= []) << dsl
|
57
|
-
end
|
58
|
-
|
59
|
-
##
|
60
|
-
# Validates a single field is of the expected type.
|
61
|
-
# Type expectations are one of:
|
62
|
-
#
|
63
|
-
# [:String] the field type must be `Symbol` or `Text`
|
64
|
-
# [:Int] the field type must be `Integer`
|
65
|
-
# [:Float] the field type must be `Number`
|
66
|
-
# [:DateTime] the field type must be 'Date'
|
67
|
-
# [:Asset] the field must be a link and the `linkType` must be `Asset`
|
68
|
-
# [:Link] the field must be a link and the `linkType` must be `Entry`.
|
69
|
-
# [:Location] the field type must be `Location`
|
70
|
-
# [:Boolean] the field type must be `Boolean`
|
71
|
-
# [:Json] the field type must be `Json` - a json blob.
|
72
|
-
# [:Array] the field must be a List.
|
73
|
-
#
|
74
|
-
# Additional validation options can be enforced:
|
75
|
-
#
|
76
|
-
# [:required] the 'Required Field' checkbox must be checked
|
77
|
-
# [:optional] the 'Required Field' checkbox must not be checked
|
78
|
-
# [:link_to] (only `:Link` or `:Array` type) the given content type(s) must be
|
79
|
-
# checked in the 'Accept only specified entry type' validations
|
80
|
-
# Example:
|
81
|
-
# validate_field :button, :Link, link_to: ['button', 'altButton']
|
82
|
-
#
|
83
|
-
# [:items] (only `:Array` type) the items of the list must be of the given type.
|
84
|
-
# Example:
|
85
|
-
# validate_field :my_strings, :Array, items: :String
|
86
|
-
#
|
87
|
-
# Examples:
|
88
|
-
# see WCC::Contentful::Model::Menu and WCC::Contentful::Model::MenuButton
|
89
|
-
def validate_field(field, type, *options)
|
90
|
-
dsl = FieldDsl.new(field, type, options)
|
91
|
-
|
92
|
-
ct = try(:content_type) || name.demodulize.camelize(:lower)
|
93
|
-
(validations[ct] ||= []) << dsl
|
94
|
-
end
|
95
|
-
|
96
|
-
##
|
97
|
-
# Accepts a content types response from the API and transforms it
|
98
|
-
# to be acceptible for the validator.
|
99
|
-
def self.transform_content_types_for_validation(content_types)
|
100
|
-
if !content_types.is_a?(Array) && items = content_types.try(:[], 'items')
|
101
|
-
content_types = items
|
102
|
-
end
|
103
|
-
|
104
|
-
# Transform the array into a hash keyed by content type ID
|
105
|
-
content_types.each_with_object({}) do |ct, ct_hash|
|
106
|
-
# Transform the fields into a hash keyed by field ID
|
107
|
-
ct['fields'] =
|
108
|
-
ct['fields'].each_with_object({}) do |f, f_hash|
|
109
|
-
f_hash[f['id']] = f
|
110
|
-
end
|
111
|
-
|
112
|
-
ct_hash[ct.dig('sys', 'id')] = ct
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
@@ -1,165 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module WCC::Contentful::ModelValidators
|
4
|
-
class ProcDsl
|
5
|
-
def to_proc
|
6
|
-
@proc
|
7
|
-
end
|
8
|
-
|
9
|
-
def initialize(proc)
|
10
|
-
@proc = proc
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
class FieldDsl
|
15
|
-
attr_reader :field
|
16
|
-
|
17
|
-
# "sections": {
|
18
|
-
# "id": "sections",
|
19
|
-
# "name": "Sections",
|
20
|
-
# "type": "Array",
|
21
|
-
# "localized": false,
|
22
|
-
# "required": false,
|
23
|
-
# "validations": [],
|
24
|
-
# "disabled": false,
|
25
|
-
# "omitted": false,
|
26
|
-
# "items": {
|
27
|
-
# "type": "Link",
|
28
|
-
# "validations": [
|
29
|
-
# {
|
30
|
-
# "linkContentType": [
|
31
|
-
# "Section"
|
32
|
-
# ]
|
33
|
-
# }
|
34
|
-
# ],
|
35
|
-
# "linkType": "Entry"
|
36
|
-
# }
|
37
|
-
# }
|
38
|
-
|
39
|
-
def schema
|
40
|
-
return @field_schema if @field_schema
|
41
|
-
|
42
|
-
# example: required('type').value(...)
|
43
|
-
type_pred = parse_type_predicate(@type)
|
44
|
-
|
45
|
-
# example: [required('required').value(eq?: true), ...]
|
46
|
-
procs =
|
47
|
-
@options.map do |opt|
|
48
|
-
if opt.is_a?(Hash)
|
49
|
-
opt.map { |k, v| parse_option(k, v) }
|
50
|
-
else
|
51
|
-
parse_option(opt)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
@field_schema =
|
56
|
-
Dry::Validation.Schema do
|
57
|
-
instance_eval(&type_pred)
|
58
|
-
|
59
|
-
procs.flatten.each { |p| instance_eval(&p) }
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def to_proc
|
64
|
-
f = field
|
65
|
-
s = schema
|
66
|
-
proc { required(f).schema(s) }
|
67
|
-
end
|
68
|
-
|
69
|
-
def initialize(field, field_type, options)
|
70
|
-
@field = field.to_s.camelize(:lower) unless field.is_a?(String)
|
71
|
-
@type = field_type
|
72
|
-
@options = options
|
73
|
-
end
|
74
|
-
|
75
|
-
private
|
76
|
-
|
77
|
-
def parse_type_predicate(type)
|
78
|
-
case type
|
79
|
-
when :String
|
80
|
-
proc { required('type').value(included_in?: %w[Symbol Text]) }
|
81
|
-
when :Int
|
82
|
-
proc { required('type').value(eql?: 'Integer') }
|
83
|
-
when :Float
|
84
|
-
proc { required('type').value(eql?: 'Number') }
|
85
|
-
when :DateTime
|
86
|
-
proc { required('type').value(eql?: 'Date') }
|
87
|
-
when :Asset
|
88
|
-
proc {
|
89
|
-
required('type').value(eql?: 'Link')
|
90
|
-
required('linkType').value(eql?: 'Asset')
|
91
|
-
}
|
92
|
-
else
|
93
|
-
proc { required('type').value(eql?: type.to_s.camelize) }
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
def parse_option(option, option_arg = nil)
|
98
|
-
case option
|
99
|
-
when :required
|
100
|
-
proc { required('required').value(eql?: true) }
|
101
|
-
when :optional
|
102
|
-
proc { required('required').value(eql?: false) }
|
103
|
-
when :link_to
|
104
|
-
link_to_proc = parse_field_link_to(option_arg)
|
105
|
-
return link_to_proc unless @type.to_s.camelize == 'Array'
|
106
|
-
proc {
|
107
|
-
required('items').schema do
|
108
|
-
required('type').value(eql?: 'Link')
|
109
|
-
instance_eval(&link_to_proc)
|
110
|
-
end
|
111
|
-
}
|
112
|
-
when :items
|
113
|
-
type_pred = parse_type_predicate(option_arg)
|
114
|
-
proc {
|
115
|
-
required('items').schema do
|
116
|
-
instance_eval(&type_pred)
|
117
|
-
end
|
118
|
-
}
|
119
|
-
else
|
120
|
-
raise ArgumentError, "unknown validation requirement: #{option}"
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
def parse_field_link_to(option_arg)
|
125
|
-
raise ArgumentError, 'validation link_to: requires an argument' unless option_arg
|
126
|
-
|
127
|
-
# this works because a Link can only have one validation in its "validations" array -
|
128
|
-
# this will fail if Contentful ever changes that.
|
129
|
-
|
130
|
-
# the 'validations' schema needs to be optional because if we get the content
|
131
|
-
# types from the CDN instead of the management API, sometimes the validations
|
132
|
-
# don't get sent back.
|
133
|
-
|
134
|
-
# "validations": [
|
135
|
-
# {
|
136
|
-
# "linkContentType": [
|
137
|
-
# "section-CardSearch",
|
138
|
-
# "section-Faq",
|
139
|
-
# "section-Testimonials",
|
140
|
-
# "section-VideoHighlight"
|
141
|
-
# ]
|
142
|
-
# }
|
143
|
-
# ]
|
144
|
-
|
145
|
-
if option_arg.is_a?(Regexp)
|
146
|
-
return proc {
|
147
|
-
optional('validations').each do
|
148
|
-
schema do
|
149
|
-
required('linkContentType').each(format?: option_arg)
|
150
|
-
end
|
151
|
-
end
|
152
|
-
}
|
153
|
-
end
|
154
|
-
|
155
|
-
option_arg = [option_arg] unless option_arg.is_a?(Array)
|
156
|
-
proc {
|
157
|
-
optional('validations').each do
|
158
|
-
schema do
|
159
|
-
required('linkContentType').value(eql?: option_arg)
|
160
|
-
end
|
161
|
-
end
|
162
|
-
}
|
163
|
-
end
|
164
|
-
end
|
165
|
-
end
|