wcc-contentful 1.1.2 → 1.3.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.
- checksums.yaml +4 -4
- data/app/controllers/wcc/contentful/webhook_controller.rb +2 -0
- data/app/jobs/wcc/contentful/webhook_enable_job.rb +1 -1
- data/lib/tasks/download_schema.rake +1 -1
- data/lib/wcc/contentful/active_record_shim.rb +2 -2
- data/lib/wcc/contentful/configuration.rb +37 -18
- data/lib/wcc/contentful/content_type_indexer.rb +2 -0
- data/lib/wcc/contentful/downloads_schema.rb +5 -4
- data/lib/wcc/contentful/engine.rb +2 -4
- data/lib/wcc/contentful/event.rb +4 -11
- data/lib/wcc/contentful/exceptions.rb +2 -3
- data/lib/wcc/contentful/indexed_representation.rb +3 -6
- data/lib/wcc/contentful/instrumentation.rb +2 -1
- data/lib/wcc/contentful/link.rb +1 -3
- data/lib/wcc/contentful/link_visitor.rb +2 -4
- data/lib/wcc/contentful/middleware/store/caching_middleware.rb +5 -9
- data/lib/wcc/contentful/middleware/store.rb +4 -6
- data/lib/wcc/contentful/model_api.rb +2 -4
- data/lib/wcc/contentful/model_builder.rb +8 -4
- data/lib/wcc/contentful/model_methods.rb +10 -12
- data/lib/wcc/contentful/model_singleton_methods.rb +2 -2
- data/lib/wcc/contentful/rich_text/node.rb +60 -0
- data/lib/wcc/contentful/rich_text.rb +105 -0
- data/lib/wcc/contentful/rspec.rb +1 -3
- data/lib/wcc/contentful/services.rb +9 -0
- data/lib/wcc/contentful/simple_client/cdn.rb +126 -0
- data/lib/wcc/contentful/simple_client/preview.rb +17 -0
- data/lib/wcc/contentful/simple_client/response.rb +47 -46
- data/lib/wcc/contentful/simple_client.rb +13 -118
- data/lib/wcc/contentful/store/base.rb +19 -27
- data/lib/wcc/contentful/store/cdn_adapter.rb +11 -7
- data/lib/wcc/contentful/store/factory.rb +1 -1
- data/lib/wcc/contentful/store/memory_store.rb +10 -7
- data/lib/wcc/contentful/store/postgres_store.rb +52 -42
- data/lib/wcc/contentful/store/query.rb +2 -2
- data/lib/wcc/contentful/store/rspec_examples/include_param.rb +6 -4
- data/lib/wcc/contentful/store/rspec_examples/operators.rb +1 -1
- data/lib/wcc/contentful/sync_engine.rb +58 -34
- data/lib/wcc/contentful/sys.rb +2 -1
- data/lib/wcc/contentful/test/double.rb +3 -5
- data/lib/wcc/contentful/test/factory.rb +4 -6
- data/lib/wcc/contentful/version.rb +1 -1
- data/lib/wcc/contentful.rb +10 -13
- data/wcc-contentful.gemspec +6 -6
- metadata +15 -25
@@ -3,7 +3,7 @@
|
|
3
3
|
module WCC::Contentful::Store
|
4
4
|
class CDNAdapter
|
5
5
|
include WCC::Contentful::Store::Interface
|
6
|
-
#
|
6
|
+
# NOTE: CDNAdapter should not instrument store events cause it's not a store.
|
7
7
|
|
8
8
|
attr_writer :client, :preview_client
|
9
9
|
|
@@ -72,9 +72,13 @@ module WCC::Contentful::Store
|
|
72
72
|
delegate :count, to: :response
|
73
73
|
|
74
74
|
def to_enum
|
75
|
-
return response.
|
75
|
+
return response.each_page.flat_map(&:page_items) unless @options[:include]
|
76
76
|
|
77
|
-
response.
|
77
|
+
response.each_page
|
78
|
+
.flat_map { |page| page.page_items.each_with_object(page).to_a }
|
79
|
+
.map do |e, page|
|
80
|
+
resolve_includes(e, page.includes, depth: @options[:include])
|
81
|
+
end
|
78
82
|
end
|
79
83
|
|
80
84
|
def initialize(store, client:, relation:, options: nil, **extra)
|
@@ -160,18 +164,18 @@ module WCC::Contentful::Store
|
|
160
164
|
end
|
161
165
|
end
|
162
166
|
|
163
|
-
def resolve_includes(entry, depth)
|
167
|
+
def resolve_includes(entry, includes, depth:)
|
164
168
|
return entry unless entry && depth && depth > 0
|
165
169
|
|
166
170
|
# Dig links out of response.includes and insert them into the entry
|
167
171
|
WCC::Contentful::LinkVisitor.new(entry, :Link, depth: depth - 1).map! do |val|
|
168
|
-
resolve_link(val)
|
172
|
+
resolve_link(val, includes)
|
169
173
|
end
|
170
174
|
end
|
171
175
|
|
172
|
-
def resolve_link(val)
|
176
|
+
def resolve_link(val, includes)
|
173
177
|
return val unless val.is_a?(Hash) && val.dig('sys', 'type') == 'Link'
|
174
|
-
return val unless included =
|
178
|
+
return val unless included = includes[val.dig('sys', 'id')]
|
175
179
|
|
176
180
|
included
|
177
181
|
end
|
@@ -9,13 +9,15 @@ module WCC::Contentful::Store
|
|
9
9
|
class MemoryStore < Base
|
10
10
|
def initialize
|
11
11
|
super
|
12
|
+
|
13
|
+
@mutex = Concurrent::ReentrantReadWriteLock.new
|
12
14
|
@hash = {}
|
13
15
|
end
|
14
16
|
|
15
17
|
def set(key, value)
|
16
18
|
value = value.deep_dup.freeze
|
17
19
|
ensure_hash value
|
18
|
-
mutex.with_write_lock do
|
20
|
+
@mutex.with_write_lock do
|
19
21
|
old = @hash[key]
|
20
22
|
@hash[key] = value
|
21
23
|
old
|
@@ -23,17 +25,17 @@ module WCC::Contentful::Store
|
|
23
25
|
end
|
24
26
|
|
25
27
|
def delete(key)
|
26
|
-
mutex.with_write_lock do
|
28
|
+
@mutex.with_write_lock do
|
27
29
|
@hash.delete(key)
|
28
30
|
end
|
29
31
|
end
|
30
32
|
|
31
33
|
def keys
|
32
|
-
mutex.with_read_lock { @hash.keys }
|
34
|
+
@mutex.with_read_lock { @hash.keys }
|
33
35
|
end
|
34
36
|
|
35
37
|
def find(key, **_options)
|
36
|
-
mutex.with_read_lock do
|
38
|
+
@mutex.with_read_lock do
|
37
39
|
@hash[key]
|
38
40
|
end
|
39
41
|
end
|
@@ -41,11 +43,12 @@ module WCC::Contentful::Store
|
|
41
43
|
SUPPORTED_OPS = %i[eq ne in nin].freeze
|
42
44
|
|
43
45
|
def execute(query)
|
44
|
-
(query.conditions.map(&:op) - SUPPORTED_OPS).
|
45
|
-
raise ArgumentError, "Operator :#{
|
46
|
+
if bad_op = (query.conditions.map(&:op) - SUPPORTED_OPS).first
|
47
|
+
raise ArgumentError, "Operator :#{bad_op} not supported"
|
46
48
|
end
|
47
49
|
|
48
|
-
|
50
|
+
# Since @hash.values returns a new array, we only need to lock here
|
51
|
+
relation = @mutex.with_read_lock { @hash.values }
|
49
52
|
|
50
53
|
# relation is an enumerable that we apply conditions to in the form of
|
51
54
|
# Enumerable#select and Enumerable#reject.
|
@@ -23,18 +23,22 @@ module WCC::Contentful::Store
|
|
23
23
|
connection_options ||= { dbname: 'postgres' }
|
24
24
|
pool_options ||= {}
|
25
25
|
@connection_pool = PostgresStore.build_connection_pool(connection_options, pool_options)
|
26
|
-
@dirty =
|
26
|
+
@dirty = Concurrent::AtomicBoolean.new
|
27
|
+
@mutex = Mutex.new
|
27
28
|
end
|
28
29
|
|
29
30
|
def set(key, value)
|
30
31
|
ensure_hash value
|
32
|
+
|
31
33
|
result =
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
34
|
+
_instrument 'upsert_entry' do
|
35
|
+
@connection_pool.with do |conn|
|
36
|
+
conn.exec_prepared('upsert_entry', [
|
37
|
+
key,
|
38
|
+
value.to_json,
|
39
|
+
quote_array(extract_links(value))
|
40
|
+
])
|
41
|
+
end
|
38
42
|
end
|
39
43
|
|
40
44
|
previous_value =
|
@@ -46,18 +50,22 @@ module WCC::Contentful::Store
|
|
46
50
|
end
|
47
51
|
|
48
52
|
if views_need_update?(value, previous_value)
|
49
|
-
#
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
53
|
+
# Mark the views as needing to be refreshed, they will be refreshed on the next query.
|
54
|
+
was_dirty = @dirty.make_true
|
55
|
+
# Send out an instrumentation event if we are the thread that marked it dirty
|
56
|
+
# (make_true returns true if the value changed)
|
57
|
+
_instrument 'mark_dirty' if was_dirty
|
54
58
|
end
|
55
59
|
|
56
60
|
previous_value
|
57
61
|
end
|
58
62
|
|
59
63
|
def keys
|
60
|
-
result =
|
64
|
+
result =
|
65
|
+
_instrument 'select_ids' do
|
66
|
+
@connection_pool.with { |conn| conn.exec_prepared('select_ids') }
|
67
|
+
end
|
68
|
+
|
61
69
|
arr = []
|
62
70
|
result.each { |r| arr << r['id'].strip }
|
63
71
|
arr
|
@@ -66,14 +74,21 @@ module WCC::Contentful::Store
|
|
66
74
|
end
|
67
75
|
|
68
76
|
def delete(key)
|
69
|
-
result =
|
77
|
+
result =
|
78
|
+
_instrument 'delete_by_id', key: key do
|
79
|
+
@connection_pool.with { |conn| conn.exec_prepared('delete_by_id', [key]) }
|
80
|
+
end
|
81
|
+
|
70
82
|
return if result.num_tuples == 0
|
71
83
|
|
72
84
|
JSON.parse(result.getvalue(0, 1))
|
73
85
|
end
|
74
86
|
|
75
87
|
def find(key, **_options)
|
76
|
-
result =
|
88
|
+
result =
|
89
|
+
_instrument 'select_entry', key: key do
|
90
|
+
@connection_pool.with { |conn| conn.exec_prepared('select_entry', [key]) }
|
91
|
+
end
|
77
92
|
return if result.num_tuples == 0
|
78
93
|
|
79
94
|
JSON.parse(result.getvalue(0, 1))
|
@@ -90,22 +105,21 @@ module WCC::Contentful::Store
|
|
90
105
|
end
|
91
106
|
|
92
107
|
def exec_query(statement, params = [])
|
93
|
-
if
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
@connection_pool.with { |conn| conn.exec_prepared('refresh_views_concurrently') }
|
108
|
+
if @dirty.true?
|
109
|
+
# Only one thread should call refresh_views_concurrently but all should wait for it to finish.
|
110
|
+
@mutex.synchronize do
|
111
|
+
# We have to check again b/c another thread may have gotten here first
|
112
|
+
if @dirty.true?
|
113
|
+
_instrument 'refresh_views' do
|
114
|
+
@connection_pool.with { |conn| conn.exec_prepared('refresh_views_concurrently') }
|
115
|
+
end
|
116
|
+
# Mark that the views have been refreshed.
|
117
|
+
@dirty.make_false
|
104
118
|
end
|
105
119
|
end
|
106
120
|
end
|
107
121
|
|
108
|
-
logger&.debug(
|
122
|
+
logger&.debug("[PostgresStore] #{statement} #{params.inspect}")
|
109
123
|
_instrument 'exec' do
|
110
124
|
@connection_pool.with { |conn| conn.exec(statement, params) }
|
111
125
|
end
|
@@ -231,16 +245,12 @@ module WCC::Contentful::Store
|
|
231
245
|
end
|
232
246
|
|
233
247
|
statement =
|
234
|
-
select_statement
|
235
|
-
" FROM #{table} AS t \n" +
|
236
|
-
joins.join("\n") + "\n" +
|
237
|
-
statement +
|
238
|
-
(limit_statement || '')
|
248
|
+
"#{select_statement} FROM #{table} AS t \n#{joins.join("\n")}\n#{statement}#{limit_statement || ''}"
|
239
249
|
|
240
250
|
[statement, params]
|
241
251
|
end
|
242
252
|
|
243
|
-
def _eq(path, expected, params)
|
253
|
+
def _eq(path, expected, params) # rubocop:disable Layout/LineContinuationLeadingSpace
|
244
254
|
return " AND t.id = $#{push_param(expected, params)}" if path == %w[sys id]
|
245
255
|
|
246
256
|
if path[3] == 'sys'
|
@@ -248,12 +258,12 @@ module WCC::Contentful::Store
|
|
248
258
|
# into it to detect whether it contains `{ "sys": { "id" => expected } }`
|
249
259
|
expected = { 'sys' => { path[4] => expected } }.to_json
|
250
260
|
return ' AND fn_contentful_jsonb_any_to_jsonb_array(t.data->' \
|
251
|
-
|
252
|
-
|
261
|
+
"#{quote_parameter_path(path.take(3))}) @> " \
|
262
|
+
"jsonb_build_array($#{push_param(expected, params)}::jsonb)"
|
253
263
|
end
|
254
264
|
|
255
|
-
" AND t.data->#{quote_parameter_path(path)}" \
|
256
|
-
"
|
265
|
+
" AND t.data->#{quote_parameter_path(path)} " \
|
266
|
+
"@> to_jsonb($#{push_param(expected, params)})"
|
257
267
|
end
|
258
268
|
|
259
269
|
PARAM_TYPES = {
|
@@ -292,7 +302,7 @@ module WCC::Contentful::Store
|
|
292
302
|
def push_join(_path, joins)
|
293
303
|
table_alias = "s#{joins.length}"
|
294
304
|
joins << "JOIN contentful_raw AS #{table_alias} ON " \
|
295
|
-
|
305
|
+
"#{table_alias}.id=ANY(t.links)"
|
296
306
|
table_alias
|
297
307
|
end
|
298
308
|
end
|
@@ -326,8 +336,8 @@ module WCC::Contentful::Store
|
|
326
336
|
end
|
327
337
|
|
328
338
|
def schema_ensured?(conn)
|
329
|
-
result = conn.exec('SELECT version FROM wcc_contentful_schema_version' \
|
330
|
-
|
339
|
+
result = conn.exec('SELECT version FROM wcc_contentful_schema_version ' \
|
340
|
+
'ORDER BY version DESC LIMIT 1')
|
331
341
|
return false if result.num_tuples == 0
|
332
342
|
|
333
343
|
result[0]['version'].to_i >= EXPECTED_VERSION
|
@@ -339,8 +349,8 @@ module WCC::Contentful::Store
|
|
339
349
|
def ensure_schema(conn)
|
340
350
|
result =
|
341
351
|
begin
|
342
|
-
conn.exec('SELECT version FROM wcc_contentful_schema_version' \
|
343
|
-
|
352
|
+
conn.exec('SELECT version FROM wcc_contentful_schema_version ' \
|
353
|
+
'ORDER BY version DESC')
|
344
354
|
rescue PG::UndefinedTable
|
345
355
|
[]
|
346
356
|
end
|
@@ -36,7 +36,7 @@ module WCC::Contentful::Store
|
|
36
36
|
|
37
37
|
FALSE_VALUES = [
|
38
38
|
false, 0,
|
39
|
-
'0', :
|
39
|
+
'0', :'0',
|
40
40
|
'f', :f,
|
41
41
|
'F', :F,
|
42
42
|
'false', :false, # rubocop:disable Lint/BooleanSymbol
|
@@ -237,7 +237,7 @@ module WCC::Contentful::Store
|
|
237
237
|
|
238
238
|
Condition =
|
239
239
|
Struct.new(:path, :op, :expected) do
|
240
|
-
LINK_KEYS = %w[id type linkType].freeze
|
240
|
+
LINK_KEYS = %w[id type linkType].freeze # rubocop:disable Lint/ConstantDefinitionInBlock
|
241
241
|
|
242
242
|
def path_tuples
|
243
243
|
@path_tuples ||=
|
@@ -15,10 +15,12 @@ RSpec.shared_examples 'supports include param' do |feature_set|
|
|
15
15
|
'fields' => {
|
16
16
|
'name' => { 'en-US' => 'root' },
|
17
17
|
'link' => { 'en-US' => make_link_to('deep1') },
|
18
|
-
'links' => {
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
'links' => {
|
19
|
+
'en-US' => [
|
20
|
+
make_link_to('shallow3'),
|
21
|
+
make_link_to('deep2')
|
22
|
+
]
|
23
|
+
}
|
22
24
|
}
|
23
25
|
}
|
24
26
|
end
|
@@ -40,7 +40,7 @@ RSpec.shared_examples 'operators' do |feature_set|
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
-
supported_operators.each do |op, value|
|
43
|
+
supported_operators.each do |op, value| # rubocop:disable Style/CombinableLoops
|
44
44
|
next unless value
|
45
45
|
|
46
46
|
it_behaves_like "supports :#{op} operator" do
|
@@ -31,15 +31,18 @@ module WCC::Contentful
|
|
31
31
|
(@state&.dup || token_wrapper_factory(nil)).freeze
|
32
32
|
end
|
33
33
|
|
34
|
-
attr_reader :store
|
35
|
-
attr_reader :client
|
34
|
+
attr_reader :store, :client, :options
|
36
35
|
|
37
36
|
def should_sync?
|
38
37
|
store&.index?
|
39
38
|
end
|
40
39
|
|
41
|
-
def initialize(
|
42
|
-
@
|
40
|
+
def initialize(client: nil, store: nil, state: nil, **options)
|
41
|
+
@options = {
|
42
|
+
key: "sync:#{object_id}"
|
43
|
+
}.merge!(options).freeze
|
44
|
+
|
45
|
+
@state_key = @options[:key] || "sync:#{object_id}"
|
43
46
|
@client = client || WCC::Contentful::Services.instance.client
|
44
47
|
@mutex = Mutex.new
|
45
48
|
|
@@ -53,9 +56,7 @@ module WCC::Contentful
|
|
53
56
|
if state
|
54
57
|
@state = token_wrapper_factory(state)
|
55
58
|
raise ArgumentError, ':state param must be a String or Hash' unless @state.is_a? Hash
|
56
|
-
unless @state.dig('sys', 'type') == 'token'
|
57
|
-
raise ArgumentError, ':state param must be of sys.type = "token"'
|
58
|
-
end
|
59
|
+
raise ArgumentError, ':state param must be of sys.type = "token"' unless @state.dig('sys', 'type') == 'token'
|
59
60
|
end
|
60
61
|
raise ArgumentError, 'either :state or :store must be provided' unless @state || @store
|
61
62
|
end
|
@@ -75,21 +76,23 @@ module WCC::Contentful
|
|
75
76
|
|
76
77
|
@mutex.synchronize do
|
77
78
|
@state ||= read_state || token_wrapper_factory(nil)
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
79
|
+
sync_token = @state['token']
|
80
|
+
|
81
|
+
next_sync_token =
|
82
|
+
client.sync(sync_token: sync_token) do |item|
|
83
|
+
id = item.dig('sys', 'id')
|
84
|
+
id_found ||= id == up_to_id
|
85
|
+
|
86
|
+
store.index(item) if store&.index?
|
87
|
+
event = WCC::Contentful::Event.from_raw(item, source: self)
|
88
|
+
yield(event) if block_given?
|
89
|
+
emit_event(event)
|
90
|
+
|
91
|
+
# Only keep the "sys" not the content in case we have a large space
|
92
|
+
all_events << WCC::Contentful::Event.from_raw(item.slice('sys'), source: self)
|
93
|
+
end
|
91
94
|
|
92
|
-
@state = @state.merge('token' =>
|
95
|
+
@state = @state.merge('token' => next_sync_token)
|
93
96
|
write_state
|
94
97
|
end
|
95
98
|
|
@@ -135,17 +138,27 @@ module WCC::Contentful
|
|
135
138
|
# This job uses the Contentful Sync API to update the configured store with
|
136
139
|
# the latest data from Contentful.
|
137
140
|
class Job < ActiveJob::Base
|
138
|
-
include WCC::Contentful::ServiceAccessors
|
139
|
-
|
140
141
|
self.queue_adapter = :async
|
141
142
|
queue_as :default
|
142
143
|
|
144
|
+
def configuration
|
145
|
+
@configuration ||= WCC::Contentful.configuration
|
146
|
+
end
|
147
|
+
|
148
|
+
def services
|
149
|
+
@services ||= WCC::Contentful::Services.instance
|
150
|
+
end
|
151
|
+
|
143
152
|
def perform(event = nil)
|
144
|
-
return unless sync_engine&.should_sync?
|
153
|
+
return unless services.sync_engine&.should_sync?
|
145
154
|
|
146
155
|
up_to_id = nil
|
147
|
-
|
148
|
-
|
156
|
+
retry_count = 0
|
157
|
+
if event
|
158
|
+
up_to_id = event[:up_to_id] || event.dig('sys', 'id')
|
159
|
+
retry_count = event[:retry_count] if event[:retry_count]
|
160
|
+
end
|
161
|
+
sync!(up_to_id: up_to_id, retry_count: retry_count)
|
149
162
|
end
|
150
163
|
|
151
164
|
# Calls the Contentful Sync API and updates the configured store with the returned
|
@@ -156,21 +169,32 @@ module WCC::Contentful
|
|
156
169
|
# If we don't find this ID in the sync data, then drop a job to try
|
157
170
|
# the sync again after a few minutes.
|
158
171
|
#
|
159
|
-
def sync!(up_to_id: nil)
|
160
|
-
id_found, count = sync_engine.next(up_to_id: up_to_id)
|
172
|
+
def sync!(up_to_id: nil, retry_count: 0)
|
173
|
+
id_found, count = services.sync_engine.next(up_to_id: up_to_id)
|
161
174
|
|
162
|
-
next_sync_token = sync_engine.state['token']
|
175
|
+
next_sync_token = services.sync_engine.state['token']
|
163
176
|
|
164
177
|
logger.info "Synced #{count} entries. Next sync token:\n #{next_sync_token}"
|
165
|
-
|
166
|
-
|
167
|
-
|
178
|
+
unless id_found
|
179
|
+
if retry_count >= configuration.sync_retry_limit
|
180
|
+
logger.error "Unable to find item with id '#{up_to_id}' on the Sync API. " \
|
181
|
+
"Abandoning after #{retry_count} retries."
|
182
|
+
else
|
183
|
+
wait = (2**retry_count) * configuration.sync_retry_wait.seconds
|
184
|
+
logger.info "Unable to find item with id '#{up_to_id}' on the Sync API. " \
|
185
|
+
"Retrying after #{wait.inspect} " \
|
186
|
+
"(#{configuration.sync_retry_limit - retry_count} retries remaining)"
|
187
|
+
|
188
|
+
self.class.set(wait: wait)
|
189
|
+
.perform_later(up_to_id: up_to_id, retry_count: retry_count + 1)
|
190
|
+
end
|
191
|
+
end
|
168
192
|
next_sync_token
|
169
193
|
end
|
170
194
|
|
171
|
-
#
|
195
|
+
# Enqueues an ActiveJob job to invoke WCC::Contentful.sync! after a given amount
|
172
196
|
# of time.
|
173
|
-
def sync_later!(up_to_id: nil, wait: 10.
|
197
|
+
def sync_later!(up_to_id: nil, wait: 10.seconds)
|
174
198
|
self.class.set(wait: wait)
|
175
199
|
.perform_later(up_to_id: up_to_id)
|
176
200
|
end
|
data/lib/wcc/contentful/sys.rb
CHANGED
@@ -11,7 +11,7 @@ WCC::Contentful::Sys =
|
|
11
11
|
:revision,
|
12
12
|
:context
|
13
13
|
) do
|
14
|
-
|
14
|
+
# rubocop:disable Lint/ConstantDefinitionInBlock
|
15
15
|
ATTRIBUTES = %i[
|
16
16
|
id
|
17
17
|
type
|
@@ -22,6 +22,7 @@ WCC::Contentful::Sys =
|
|
22
22
|
revision
|
23
23
|
context
|
24
24
|
].freeze
|
25
|
+
# rubocop:enable Lint/ConstantDefinitionInBlock
|
25
26
|
|
26
27
|
undef []=
|
27
28
|
ATTRIBUTES.each { |a| __send__(:undef_method, "#{a}=") }
|
@@ -8,9 +8,7 @@ module WCC::Contentful::Test::Double
|
|
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
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
|
11
|
+
const = WCC::Contentful::Model.resolve_constant(const.to_s) unless const.respond_to?(:content_type_definition)
|
14
12
|
attrs.symbolize_keys!
|
15
13
|
|
16
14
|
bad_attrs = attrs.reject { |a| const.instance_methods.include?(a) }
|
@@ -45,7 +43,7 @@ module WCC::Contentful::Test::Double
|
|
45
43
|
sys: {
|
46
44
|
type: 'Link',
|
47
45
|
linkType: 'Space',
|
48
|
-
id: ENV
|
46
|
+
id: ENV.fetch('CONTENTFUL_SPACE_ID', nil)
|
49
47
|
}
|
50
48
|
},
|
51
49
|
id: SecureRandom.urlsafe_base64,
|
@@ -62,7 +60,7 @@ module WCC::Contentful::Test::Double
|
|
62
60
|
revision: rand(100),
|
63
61
|
locale: 'en-US'
|
64
62
|
},
|
65
|
-
fields: attrs.
|
63
|
+
fields: attrs.transform_values { |v| { 'en-US' => v } }
|
66
64
|
}
|
67
65
|
|
68
66
|
double(attrs)
|
@@ -8,9 +8,7 @@ module WCC::Contentful::Test::Factory
|
|
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
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
|
11
|
+
const = WCC::Contentful::Model.resolve_constant(const.to_s) unless const.respond_to?(:content_type_definition)
|
14
12
|
attrs = attrs.transform_keys { |a| a.to_s.camelize(:lower) }
|
15
13
|
|
16
14
|
id = attrs.delete('id')
|
@@ -59,7 +57,7 @@ module WCC::Contentful::Test::Factory
|
|
59
57
|
sys: {
|
60
58
|
type: 'Link',
|
61
59
|
linkType: 'Space',
|
62
|
-
id: ENV
|
60
|
+
id: ENV.fetch('CONTENTFUL_SPACE_ID', nil)
|
63
61
|
}
|
64
62
|
},
|
65
63
|
id: id || SecureRandom.urlsafe_base64,
|
@@ -86,8 +84,8 @@ module WCC::Contentful::Test::Factory
|
|
86
84
|
end
|
87
85
|
|
88
86
|
def contentful_fields(model)
|
89
|
-
WCC::Contentful::Test::Attributes.defaults(model).
|
90
|
-
|
87
|
+
WCC::Contentful::Test::Attributes.defaults(model).transform_values do |v|
|
88
|
+
{ 'en-US' => v }
|
91
89
|
end
|
92
90
|
end
|
93
91
|
|
data/lib/wcc/contentful.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
require 'wcc/contentful/version'
|
4
4
|
|
5
5
|
require 'active_support'
|
6
|
-
require 'active_support/
|
6
|
+
require 'active_support/all'
|
7
7
|
|
8
8
|
require 'wcc/contentful/active_record_shim'
|
9
9
|
require 'wcc/contentful/configuration'
|
@@ -46,9 +46,8 @@ module WCC::Contentful
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def logger
|
49
|
-
|
50
|
-
|
51
|
-
@logger ||= Logger.new(STDERR)
|
49
|
+
ActiveSupport::Deprecation.warn('Use WCC::Contentful::Services.instance.logger instead')
|
50
|
+
WCC::Contentful::Services.instance.logger
|
52
51
|
end
|
53
52
|
end
|
54
53
|
|
@@ -82,7 +81,7 @@ module WCC::Contentful
|
|
82
81
|
|
83
82
|
if configuration.update_schema_file == :always ||
|
84
83
|
(configuration.update_schema_file == :if_possible && Services.instance.management_client) ||
|
85
|
-
configuration.update_schema_file == :if_missing && !File.exist?(configuration.schema_file)
|
84
|
+
(configuration.update_schema_file == :if_missing && !File.exist?(configuration.schema_file))
|
86
85
|
|
87
86
|
begin
|
88
87
|
downloader = WCC::Contentful::DownloadsSchema.new
|
@@ -90,17 +89,15 @@ module WCC::Contentful
|
|
90
89
|
rescue WCC::Contentful::SimpleClient::ApiError => e
|
91
90
|
raise InitializationError, e if configuration.update_schema_file == :always
|
92
91
|
|
93
|
-
|
92
|
+
Services.instance.logger.warn("Unable to download schema from management API - #{e.message}")
|
94
93
|
end
|
95
94
|
end
|
96
95
|
|
97
96
|
content_types =
|
98
97
|
begin
|
99
|
-
if File.exist?(configuration.schema_file)
|
100
|
-
JSON.parse(File.read(configuration.schema_file))['contentTypes']
|
101
|
-
end
|
98
|
+
JSON.parse(File.read(configuration.schema_file))['contentTypes'] if File.exist?(configuration.schema_file)
|
102
99
|
rescue JSON::ParserError
|
103
|
-
|
100
|
+
Services.instance.warn("Schema file invalid, ignoring it: #{configuration.schema_file}")
|
104
101
|
nil
|
105
102
|
end
|
106
103
|
|
@@ -114,13 +111,13 @@ module WCC::Contentful
|
|
114
111
|
content_types = client.content_types(limit: 1000).items if client
|
115
112
|
rescue WCC::Contentful::SimpleClient::ApiError => e
|
116
113
|
# indicates bad credentials
|
117
|
-
|
114
|
+
Services.instance.logger.warn("Unable to load content types from API - #{e.message}")
|
118
115
|
end
|
119
116
|
end
|
120
117
|
|
121
118
|
unless content_types
|
122
|
-
raise InitializationError, 'Unable to load content types from schema file or API!' \
|
123
|
-
|
119
|
+
raise InitializationError, 'Unable to load content types from schema file or API! ' \
|
120
|
+
'Check your access token and space ID.'
|
124
121
|
end
|
125
122
|
|
126
123
|
# Set the schema on the default WCC::Contentful::Model
|