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
data/lib/wcc/contentful.rb
CHANGED
@@ -8,82 +8,39 @@ require 'active_support/core_ext/object'
|
|
8
8
|
require 'wcc/contentful/configuration'
|
9
9
|
require 'wcc/contentful/exceptions'
|
10
10
|
require 'wcc/contentful/helpers'
|
11
|
+
require 'wcc/contentful/services'
|
11
12
|
require 'wcc/contentful/simple_client'
|
12
13
|
require 'wcc/contentful/store'
|
13
14
|
require 'wcc/contentful/content_type_indexer'
|
14
|
-
require 'wcc/contentful/model_validators'
|
15
15
|
require 'wcc/contentful/model'
|
16
|
+
require 'wcc/contentful/model_methods'
|
17
|
+
require 'wcc/contentful/model_singleton_methods'
|
16
18
|
require 'wcc/contentful/model_builder'
|
17
19
|
|
18
|
-
##
|
19
20
|
# The root namespace of the wcc-contentful gem
|
20
21
|
#
|
21
22
|
# Initialize the gem with the `configure` and `init` methods inside your
|
22
23
|
# initializer.
|
23
24
|
module WCC::Contentful
|
24
25
|
class << self
|
25
|
-
##
|
26
26
|
# Gets the current configuration, after calling WCC::Contentful.configure
|
27
27
|
attr_reader :configuration
|
28
28
|
|
29
|
-
|
30
|
-
# Gets the sync token that was returned by the Contentful CDN after the most
|
31
|
-
# recent invocation of WCC::Contentful.sync!
|
32
|
-
attr_reader :next_sync_token
|
29
|
+
attr_reader :types
|
33
30
|
end
|
34
31
|
|
35
|
-
##
|
36
|
-
# Gets a {CDN Client}[rdoc-ref:WCC::Contentful::SimpleClient::Cdn] which provides
|
37
|
-
# methods for getting and paging raw JSON data from the Contentful CDN.
|
38
|
-
def self.client(preview: false)
|
39
|
-
if preview
|
40
|
-
configuration&.preview_client
|
41
|
-
else
|
42
|
-
configuration&.client
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
##
|
47
|
-
# Gets the data-store which executes the queries run against the dynamic
|
48
|
-
# models in the WCC::Contentful::Model namespace.
|
49
|
-
# This is one of the following based on the configured content_delivery method:
|
50
|
-
#
|
51
|
-
# [:direct] an instance of WCC::Contentful::Store::CDNAdapter with a
|
52
|
-
# {CDN Client}[rdoc-ref:WCC::Contentful::SimpleClient::Cdn] to access the CDN.
|
53
|
-
#
|
54
|
-
# [:lazy_sync] an instance of WCC::Contentful::Store::LazyCacheStore
|
55
|
-
# with the configured ActiveSupport::Cache implementation and a
|
56
|
-
# {CDN Client}[rdoc-ref:WCC::Contentful::SimpleClient::Cdn] for when data
|
57
|
-
# cannot be found in the cache.
|
58
|
-
#
|
59
|
-
# [:eager_sync] an instance of the configured Store type, defined by
|
60
|
-
# WCC::Contentful::Configuration.sync_store
|
61
|
-
#
|
62
|
-
def self.store
|
63
|
-
WCC::Contentful::Model.store
|
64
|
-
end
|
65
|
-
|
66
|
-
def self.preview_store
|
67
|
-
WCC::Contentful::Model.preview_store
|
68
|
-
end
|
69
|
-
|
70
|
-
##
|
71
32
|
# Configures the WCC::Contentful gem to talk to a Contentful space.
|
72
33
|
# This must be called first in your initializer, before #init! or accessing the
|
73
34
|
# client.
|
74
35
|
def self.configure
|
75
36
|
@configuration ||= Configuration.new
|
76
|
-
@next_sync_token = nil
|
77
37
|
yield(configuration)
|
78
38
|
|
79
39
|
configuration.validate!
|
80
40
|
|
81
|
-
configuration.configure_contentful
|
82
|
-
|
83
41
|
configuration
|
84
42
|
end
|
85
43
|
|
86
|
-
##
|
87
44
|
# Initializes the WCC::Contentful model-space and backing store.
|
88
45
|
# This populates the WCC::Contentful::Model namespace with Ruby classes
|
89
46
|
# that represent content types in the configured Contentful space.
|
@@ -91,24 +48,17 @@ module WCC::Contentful
|
|
91
48
|
# These content types can be queried directly:
|
92
49
|
# WCC::Contentful::Model::Page.find('1xab...')
|
93
50
|
# Or you can inherit from them in your own app:
|
94
|
-
# class Page < WCC::Contentful::Model
|
51
|
+
# class Page < WCC::Contentful::Model::Page; end
|
95
52
|
# Page.find_by(slug: 'about-us')
|
96
53
|
def self.init!
|
97
54
|
raise ArgumentError, 'Please first call WCC:Contentful.configure' if configuration.nil?
|
98
|
-
@mutex ||= Mutex.new
|
99
|
-
|
100
|
-
use_preview_client = false
|
101
|
-
# we want as much as possible the raw JSON from the API
|
102
|
-
content_types_resp =
|
103
|
-
if configuration.management_client
|
104
|
-
configuration.management_client.content_types(limit: 1000)
|
105
|
-
else
|
106
|
-
configuration.client.content_types(limit: 1000)
|
107
|
-
end
|
108
55
|
|
109
|
-
|
56
|
+
# we want as much as possible the raw JSON from the API so use the management
|
57
|
+
# client if possible
|
58
|
+
client = Services.instance.management_client ||
|
59
|
+
Services.instance.client
|
110
60
|
|
111
|
-
@content_types =
|
61
|
+
@content_types = client.content_types(limit: 1000).items
|
112
62
|
|
113
63
|
indexer =
|
114
64
|
ContentTypeIndexer.new.tap do |ixr|
|
@@ -116,92 +66,14 @@ module WCC::Contentful
|
|
116
66
|
end
|
117
67
|
@types = indexer.types
|
118
68
|
|
119
|
-
|
120
|
-
store = configuration.store(preview: false)
|
121
|
-
WCC::Contentful::Model.store = store
|
122
|
-
preview_store = configuration.store(preview: use_preview_client)
|
123
|
-
WCC::Contentful::Model.preview_store = preview_store
|
124
|
-
else
|
125
|
-
store = configuration.store(preview: use_preview_client)
|
126
|
-
WCC::Contentful::Model.store = store
|
127
|
-
end
|
128
|
-
|
69
|
+
store = Services.instance.store
|
129
70
|
if store.respond_to?(:index)
|
130
|
-
|
131
|
-
|
71
|
+
# Drop an initial sync
|
72
|
+
WCC::Contentful::DelayedSyncJob.perform_later
|
132
73
|
end
|
133
74
|
|
134
75
|
WCC::Contentful::ModelBuilder.new(@types).build_models
|
135
76
|
|
136
|
-
|
137
|
-
@types.each_value do |t|
|
138
|
-
file = File.dirname(__FILE__) + "/contentful/model/#{t.name.underscore}.rb"
|
139
|
-
require file if File.exist?(file)
|
140
|
-
end
|
77
|
+
require_relative 'contentful/client_ext' if defined?(::Contentful)
|
141
78
|
end
|
142
|
-
|
143
|
-
##
|
144
|
-
# Runs validations over the content types returned from the Contentful API.
|
145
|
-
# Validations are configured on predefined model classes using the
|
146
|
-
# `validate_field` directive. Example:
|
147
|
-
# validate_field :top_button, :Link, :optional, link_to: 'menuButton'
|
148
|
-
# This results in a WCC::Contentful::ValidationError
|
149
|
-
# if the 'topButton' field in the 'menu' content type is not a link.
|
150
|
-
def self.validate_models!
|
151
|
-
# Ensure application models are loaded before we validate
|
152
|
-
Dir[Rails.root.join('app/models/**/*.rb')].each { |file| require file } if defined?(Rails)
|
153
|
-
|
154
|
-
content_types = WCC::Contentful::ModelValidators.transform_content_types_for_validation(
|
155
|
-
@content_types
|
156
|
-
)
|
157
|
-
errors = WCC::Contentful::Model.schema.call(content_types)
|
158
|
-
raise WCC::Contentful::ValidationError, errors.errors unless errors.success?
|
159
|
-
end
|
160
|
-
|
161
|
-
##
|
162
|
-
# Calls the Contentful Sync API and updates the configured store with the returned
|
163
|
-
# data.
|
164
|
-
#
|
165
|
-
# up_to_id: An ID that we know has changed and should come back from the sync.
|
166
|
-
# If we don't find this ID in the sync data, then drop a job to try
|
167
|
-
# the sync again after a few minutes.
|
168
|
-
#
|
169
|
-
def self.sync!(up_to_id: nil)
|
170
|
-
return unless store.respond_to?(:index)
|
171
|
-
|
172
|
-
@mutex.synchronize do
|
173
|
-
sync_resp = client.sync(sync_token: next_sync_token)
|
174
|
-
|
175
|
-
id_found = up_to_id.nil?
|
176
|
-
|
177
|
-
sync_resp.items.each do |item|
|
178
|
-
id = item.dig('sys', 'id')
|
179
|
-
id_found ||= id == up_to_id
|
180
|
-
store.index(item)
|
181
|
-
end
|
182
|
-
store.set("sync:#{configuration.space}:token", sync_resp.next_sync_token)
|
183
|
-
@next_sync_token = sync_resp.next_sync_token
|
184
|
-
|
185
|
-
unless id_found
|
186
|
-
raise SyncError, "ID '#{up_to_id}' did not come back via sync." unless defined?(Rails)
|
187
|
-
sync_later!(up_to_id: up_to_id)
|
188
|
-
end
|
189
|
-
next_sync_token
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
|
-
##
|
194
|
-
# Drops an ActiveJob job to invoke WCC::Contentful.sync! after a given amount
|
195
|
-
# of time.
|
196
|
-
def self.sync_later!(up_to_id: nil, wait: 10.minutes)
|
197
|
-
raise NotImplementedError, 'Cannot sync_later! outside of a Rails app' unless defined?(Rails)
|
198
|
-
|
199
|
-
WCC::Contentful::DelayedSyncJob.set(wait: wait).perform_later(up_to_id)
|
200
|
-
end
|
201
|
-
|
202
|
-
# TODO: https://zube.io/watermarkchurch/development/c/2234 init graphql
|
203
|
-
# def self.init_graphql!
|
204
|
-
# require 'wcc/contentful/graphql'
|
205
|
-
# etc...
|
206
|
-
# end
|
207
79
|
end
|
@@ -5,11 +5,24 @@ class Contentful::Client
|
|
5
5
|
alias_method :old_get_http, :get_http
|
6
6
|
end
|
7
7
|
|
8
|
+
def self.adapter
|
9
|
+
@adapter ||=
|
10
|
+
WCC::Contentful::SimpleClient.load_adapter(WCC::Contentful.configuration.http_adapter) ||
|
11
|
+
->(url, query, headers, proxy) { old_get_http(url, query, headers, proxy) }
|
12
|
+
end
|
13
|
+
|
8
14
|
def self.get_http(url, query, headers = {}, proxy = {})
|
9
|
-
if
|
10
|
-
|
11
|
-
else
|
12
|
-
old_get_http(url, query, headers, proxy)
|
15
|
+
if environment = WCC::Contentful.configuration.environment
|
16
|
+
url = rewrite_to_environment(url, environment)
|
13
17
|
end
|
18
|
+
|
19
|
+
adapter.call(url, query, headers, proxy)
|
20
|
+
end
|
21
|
+
|
22
|
+
REWRITE_REGEXP = /^(https?\:\/\/(?:\w+)\.contentful\.com\/spaces\/[^\/]+\/)(?!environments)(.+)$/
|
23
|
+
def self.rewrite_to_environment(url, environment)
|
24
|
+
return url unless m = REWRITE_REGEXP.match(url)
|
25
|
+
|
26
|
+
File.join(m[1], 'environments', environment, m[2])
|
14
27
|
end
|
15
28
|
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
class WCC::Contentful::Configuration
|
4
4
|
ATTRIBUTES = %i[
|
5
5
|
access_token
|
6
|
+
app_url
|
6
7
|
management_token
|
7
8
|
space
|
8
9
|
environment
|
@@ -13,23 +14,28 @@ class WCC::Contentful::Configuration
|
|
13
14
|
sync_cache_store
|
14
15
|
webhook_username
|
15
16
|
webhook_password
|
17
|
+
webhook_jobs
|
16
18
|
].freeze
|
17
19
|
attr_accessor(*ATTRIBUTES)
|
18
20
|
|
19
|
-
|
21
|
+
# Returns true if the currently configured environment is pointing at `master`.
|
22
|
+
def master?
|
23
|
+
!environment.present?
|
24
|
+
end
|
25
|
+
|
20
26
|
# Defines the method by which content is downloaded from the Contentful CDN.
|
21
27
|
#
|
22
28
|
# [:direct] `config.content_delivery = :direct`
|
23
29
|
# with the `:direct` method, all queries result in web requests to
|
24
30
|
# 'https://cdn.contentful.com' via the
|
25
|
-
# {
|
31
|
+
# {WCC::Contentful::SimpleClient::Cdn SimpleClient}
|
26
32
|
#
|
27
33
|
# [:eager_sync] `config.content_delivery = :eager_sync, [sync_store], [options]`
|
28
34
|
# with the `:eager_sync` method, the entire content of the Contentful
|
29
35
|
# space is downloaded locally and stored in the
|
30
|
-
# {
|
31
|
-
# to periodically call `WCC::Contentful.sync!` to keep the store
|
32
|
-
# Alternatively, the provided {
|
36
|
+
# {WCC::Contentful::Services#store configured store}. The application is
|
37
|
+
# responsible to periodically call `WCC::Contentful.sync!` to keep the store
|
38
|
+
# updated. Alternatively, the provided {WCC::Contentful::Engine Engine}
|
33
39
|
# can be mounted to receive a webhook from the Contentful space
|
34
40
|
# on publish events:
|
35
41
|
# mount WCC::Contentful::Engine, at: '/wcc/contentful'
|
@@ -51,6 +57,7 @@ class WCC::Contentful::Configuration
|
|
51
57
|
|
52
58
|
WCC::Contentful::Store::Factory.new(
|
53
59
|
self,
|
60
|
+
nil,
|
54
61
|
cd,
|
55
62
|
cd_params
|
56
63
|
).validate!
|
@@ -59,31 +66,18 @@ class WCC::Contentful::Configuration
|
|
59
66
|
@content_delivery_params = cd_params
|
60
67
|
end
|
61
68
|
|
62
|
-
|
63
|
-
# Initializes the configured Sync Store.
|
64
|
-
def store(preview: false)
|
65
|
-
if preview
|
66
|
-
@preview_store ||= WCC::Contentful::Store::Factory.new(
|
67
|
-
self,
|
68
|
-
:direct,
|
69
|
-
[{ preview: preview }]
|
70
|
-
).build_sync_store
|
71
|
-
else
|
72
|
-
@store ||= WCC::Contentful::Store::Factory.new(
|
73
|
-
self,
|
74
|
-
@content_delivery,
|
75
|
-
@content_delivery_params
|
76
|
-
).build_sync_store
|
77
|
-
end
|
78
|
-
end
|
69
|
+
attr_reader :content_delivery_params
|
79
70
|
|
80
|
-
##
|
81
71
|
# Directly sets the adapter layer for communicating with Contentful
|
82
72
|
def store=(value)
|
83
73
|
@content_delivery = :custom
|
84
|
-
|
74
|
+
store, *cd_params = value
|
75
|
+
@store = store
|
76
|
+
@content_delivery_params = cd_params
|
85
77
|
end
|
86
78
|
|
79
|
+
attr_reader :store
|
80
|
+
|
87
81
|
# Sets the adapter which is used to make HTTP requests.
|
88
82
|
# If left unset, the gem attempts to load either 'http' or 'typhoeus'.
|
89
83
|
# You can pass your own adapter which responds to 'call', or even a lambda
|
@@ -93,76 +87,23 @@ class WCC::Contentful::Configuration
|
|
93
87
|
|
94
88
|
def initialize
|
95
89
|
@access_token = ''
|
90
|
+
@app_url = ENV['APP_URL']
|
96
91
|
@management_token = ''
|
97
92
|
@preview_token = ''
|
98
93
|
@space = ''
|
99
94
|
@default_locale = nil
|
100
95
|
@content_delivery = :direct
|
101
|
-
|
102
|
-
|
103
|
-
##
|
104
|
-
# Gets a {CDN Client}[rdoc-ref:WCC::Contentful::SimpleClient::Cdn] which provides
|
105
|
-
# methods for getting and paging raw JSON data from the Contentful CDN.
|
106
|
-
attr_reader :client
|
107
|
-
attr_reader :management_client
|
108
|
-
attr_reader :preview_client
|
109
|
-
|
110
|
-
##
|
111
|
-
# Called by WCC::Contentful.init! to configure the
|
112
|
-
# Contentful clients. This method can be called independently of `init!` if
|
113
|
-
# the application would prefer not to generate all the models.
|
114
|
-
#
|
115
|
-
# If the {contentful.rb}[https://github.com/contentful/contentful.rb] gem is
|
116
|
-
# loaded, it is extended to make use of the `http_adapter` lambda.
|
117
|
-
def configure_contentful
|
118
|
-
@client = nil
|
119
|
-
@management_client = nil
|
120
|
-
@preview_client = nil
|
121
|
-
|
122
|
-
if defined?(::ContentfulModel)
|
123
|
-
ContentfulModel.configure do |config|
|
124
|
-
config.access_token = access_token
|
125
|
-
config.management_token = management_token if management_token.present?
|
126
|
-
config.space = space
|
127
|
-
config.default_locale = default_locale || 'en-US'
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
require_relative 'client_ext' if defined?(::Contentful)
|
132
|
-
|
133
|
-
@client = WCC::Contentful::SimpleClient::Cdn.new(
|
134
|
-
access_token: access_token,
|
135
|
-
space: space,
|
136
|
-
default_locale: default_locale,
|
137
|
-
adapter: http_adapter,
|
138
|
-
environment: environment
|
139
|
-
)
|
140
|
-
|
141
|
-
if preview_token.present?
|
142
|
-
@preview_client = WCC::Contentful::SimpleClient::Preview.new(
|
143
|
-
preview_token: preview_token,
|
144
|
-
space: space,
|
145
|
-
default_locale: default_locale,
|
146
|
-
adapter: http_adapter
|
147
|
-
)
|
148
|
-
end
|
149
|
-
|
150
|
-
return unless management_token.present?
|
151
|
-
@management_client = WCC::Contentful::SimpleClient::Management.new(
|
152
|
-
management_token: management_token,
|
153
|
-
space: space,
|
154
|
-
default_locale: default_locale,
|
155
|
-
adapter: http_adapter,
|
156
|
-
environment: environment
|
157
|
-
)
|
96
|
+
@webhook_jobs = []
|
158
97
|
end
|
159
98
|
|
160
99
|
def validate!
|
161
100
|
raise ArgumentError, 'Please provide "space"' unless space.present?
|
162
101
|
raise ArgumentError, 'Please provide "access_token"' unless access_token.present?
|
163
102
|
|
164
|
-
|
165
|
-
|
166
|
-
|
103
|
+
webhook_jobs&.each do |job|
|
104
|
+
next if job.respond_to?(:call) || job.respond_to?(:perform_later)
|
105
|
+
|
106
|
+
raise ArgumentError, "The job '#{job}' must be an instance of ActiveJob::Base or respond to :call"
|
107
|
+
end
|
167
108
|
end
|
168
109
|
end
|
@@ -4,6 +4,25 @@ module WCC::Contentful
|
|
4
4
|
class Engine < ::Rails::Engine
|
5
5
|
isolate_namespace WCC::Contentful
|
6
6
|
|
7
|
+
initializer 'enable webhook' do
|
8
|
+
config = WCC::Contentful.configuration
|
9
|
+
next unless config&.management_token.present?
|
10
|
+
next unless config.app_url.present?
|
11
|
+
|
12
|
+
if Rails.env.production?
|
13
|
+
WebhookEnableJob.set(wait: 10.seconds).perform_later(
|
14
|
+
management_token: config.management_token,
|
15
|
+
app_url: config.app_url,
|
16
|
+
space: config.space,
|
17
|
+
environment: config.environment,
|
18
|
+
default_locale: config.default_locale,
|
19
|
+
adapter: config.http_adapter,
|
20
|
+
webhook_username: config.webhook_username,
|
21
|
+
webhook_password: config.webhook_password
|
22
|
+
)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
7
26
|
config.generators do |g|
|
8
27
|
g.test_framework :rspec, fixture: false
|
9
28
|
end
|
@@ -1,40 +1,37 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module WCC::Contentful
|
4
|
-
class
|
5
|
-
|
6
|
-
Struct.new(:path, :error) do
|
7
|
-
def to_s
|
8
|
-
"#{path}: #{error}"
|
9
|
-
end
|
10
|
-
end
|
4
|
+
class SyncError < StandardError
|
5
|
+
end
|
11
6
|
|
12
|
-
|
7
|
+
# Raised when a constant under {WCC::Contentful::Model} does not match to a
|
8
|
+
# content type in the configured Contentful space
|
9
|
+
class ContentTypeNotFoundError < NameError
|
10
|
+
end
|
13
11
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
12
|
+
# Raised when an entry contains a circular reference and cannot be represented
|
13
|
+
# as a flat tree.
|
14
|
+
class CircularReferenceError < StandardError
|
15
|
+
attr_reader :stack
|
16
|
+
attr_reader :id
|
18
17
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
hash.map do |k, v|
|
24
|
-
if v.is_a?(Hash)
|
25
|
-
msgs = join_msg_keys(v)
|
26
|
-
msgs.map { |msg| Message.new(k.to_s + '.' + msg.path, msg.error) }
|
27
|
-
else
|
28
|
-
v.map { |msg| Message.new(k.to_s, msg) }
|
29
|
-
end
|
30
|
-
end
|
31
|
-
ret.flatten(1)
|
18
|
+
def initialize(stack, id)
|
19
|
+
@id = id
|
20
|
+
@stack = stack.slice(stack.index(id)..stack.length)
|
21
|
+
super('Circular reference detected!')
|
32
22
|
end
|
33
|
-
end
|
34
23
|
|
35
|
-
|
24
|
+
def message
|
25
|
+
return super unless stack
|
26
|
+
|
27
|
+
super + "\n " \
|
28
|
+
"#{stack.last} points to #{id} which is also it's ancestor\n " +
|
29
|
+
stack.join('->')
|
30
|
+
end
|
36
31
|
end
|
37
32
|
|
38
|
-
|
33
|
+
# Raised by {WCC::Contentful::ModelMethods#resolve Model#resolve} when attempting
|
34
|
+
# to resolve an entry's links and that entry cannot be found in the space.
|
35
|
+
class ResolveError < StandardError
|
39
36
|
end
|
40
37
|
end
|