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
@@ -11,63 +11,133 @@ module WCC::Contentful::Store
|
|
11
11
|
@client = client
|
12
12
|
end
|
13
13
|
|
14
|
-
def find(key)
|
14
|
+
def find(key, hint: nil, **options)
|
15
|
+
options = { locale: '*' }.merge!(options || {})
|
15
16
|
entry =
|
16
|
-
|
17
|
-
client.
|
18
|
-
|
19
|
-
|
17
|
+
if hint
|
18
|
+
client.public_send(hint.underscore, key, options)
|
19
|
+
else
|
20
|
+
begin
|
21
|
+
client.entry(key, options)
|
22
|
+
rescue WCC::Contentful::SimpleClient::NotFoundError
|
23
|
+
client.asset(key, options)
|
24
|
+
end
|
20
25
|
end
|
21
26
|
entry&.raw
|
22
27
|
rescue WCC::Contentful::SimpleClient::NotFoundError
|
23
28
|
nil
|
24
29
|
end
|
25
30
|
|
26
|
-
def find_by(content_type:, filter: nil)
|
31
|
+
def find_by(content_type:, filter: nil, options: nil)
|
27
32
|
# default implementation - can be overridden
|
28
|
-
q = find_all(content_type: content_type)
|
33
|
+
q = find_all(content_type: content_type, options: { limit: 1 }.merge!(options || {}))
|
29
34
|
q = q.apply(filter) if filter
|
30
35
|
q.first
|
31
36
|
end
|
32
37
|
|
33
|
-
def find_all(content_type:)
|
34
|
-
Query.new(
|
38
|
+
def find_all(content_type:, options: nil)
|
39
|
+
Query.new(
|
40
|
+
store: self,
|
41
|
+
client: @client,
|
42
|
+
relation: { content_type: content_type },
|
43
|
+
options: options
|
44
|
+
)
|
35
45
|
end
|
36
46
|
|
37
47
|
class Query < Base::Query
|
38
|
-
delegate :count, to: :
|
48
|
+
delegate :count, to: :response
|
39
49
|
|
40
50
|
def result
|
41
|
-
|
51
|
+
return response.items unless @options[:include]
|
52
|
+
|
53
|
+
response.items.map { |e| resolve_includes(e, @options[:include]) }
|
42
54
|
end
|
43
55
|
|
44
|
-
def initialize(client,
|
56
|
+
def initialize(store:, client:, relation:, options: nil, **extra)
|
45
57
|
raise ArgumentError, 'Client cannot be nil' unless client.present?
|
46
58
|
raise ArgumentError, 'content_type must be provided' unless relation[:content_type].present?
|
59
|
+
|
60
|
+
super(store)
|
47
61
|
@client = client
|
48
62
|
@relation = relation
|
63
|
+
@options = options || {}
|
64
|
+
@extra = extra || {}
|
49
65
|
end
|
50
66
|
|
51
|
-
def
|
52
|
-
|
53
|
-
locale
|
54
|
-
|
55
|
-
|
67
|
+
def apply_operator(operator, field, expected, context = nil)
|
68
|
+
op = operator == :eq ? nil : operator
|
69
|
+
param = parameter(field, operator: op, context: context, locale: true)
|
70
|
+
|
71
|
+
self.class.new(
|
72
|
+
store: @store,
|
73
|
+
client: @client,
|
74
|
+
relation: @relation.merge(param => expected),
|
75
|
+
options: @options,
|
76
|
+
**@extra
|
77
|
+
)
|
78
|
+
end
|
79
|
+
|
80
|
+
def nested_conditions(field, conditions, context)
|
81
|
+
base_param = parameter(field)
|
82
|
+
|
83
|
+
conditions.reduce(self) do |query, (ref, value)|
|
84
|
+
query.apply({ "#{base_param}.#{parameter(ref)}" => value }, context)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
Base::Query::OPERATORS.each do |op|
|
89
|
+
define_method(op) do |field, expected, context = nil|
|
90
|
+
apply_operator(op, field, expected, context)
|
91
|
+
end
|
56
92
|
end
|
57
93
|
|
58
94
|
private
|
59
95
|
|
60
|
-
def
|
61
|
-
|
62
|
-
@resolve ||=
|
96
|
+
def response
|
97
|
+
@response ||=
|
63
98
|
if @relation[:content_type] == 'Asset'
|
64
99
|
@client.assets(
|
65
|
-
{ locale: '*' }.merge!(@relation.reject { |k| k == :content_type })
|
100
|
+
{ locale: '*' }.merge!(@relation.reject { |k| k == :content_type }).merge!(@options)
|
66
101
|
)
|
67
102
|
else
|
68
|
-
@client.entries({ locale: '*' }.merge!(@relation))
|
103
|
+
@client.entries({ locale: '*' }.merge!(@relation).merge!(@options))
|
69
104
|
end
|
70
105
|
end
|
106
|
+
|
107
|
+
def resolve_link(val, depth)
|
108
|
+
return val unless val.is_a?(Hash) && val.dig('sys', 'type') == 'Link'
|
109
|
+
return val unless included = response.includes[val.dig('sys', 'id')]
|
110
|
+
|
111
|
+
resolve_includes(included, depth - 1)
|
112
|
+
end
|
113
|
+
|
114
|
+
def parameter(field, operator: nil, context: nil, locale: false)
|
115
|
+
if sys?(field)
|
116
|
+
"#{field}#{op_param(operator)}"
|
117
|
+
elsif id?(field)
|
118
|
+
"sys.#{field}#{op_param(operator)}"
|
119
|
+
else
|
120
|
+
"#{field_reference(field)}#{locale(context) if locale}#{op_param(operator)}"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def locale(context)
|
125
|
+
".#{(context || {}).fetch(:locale, 'en-US')}"
|
126
|
+
end
|
127
|
+
|
128
|
+
def op_param(operator)
|
129
|
+
operator ? "[#{operator}]" : ''
|
130
|
+
end
|
131
|
+
|
132
|
+
def field_reference(field)
|
133
|
+
return field if nested?(field)
|
134
|
+
|
135
|
+
"fields.#{field}"
|
136
|
+
end
|
137
|
+
|
138
|
+
def nested?(field)
|
139
|
+
field.to_s.include?('.')
|
140
|
+
end
|
71
141
|
end
|
72
142
|
end
|
73
143
|
end
|
@@ -2,24 +2,18 @@
|
|
2
2
|
|
3
3
|
module WCC::Contentful::Store
|
4
4
|
class LazyCacheStore
|
5
|
-
delegate :find_all, to: :@cdn
|
6
|
-
|
7
|
-
# TODO: https://zube.io/watermarkchurch/development/c/2265
|
8
|
-
# figure out how to cache the results of a find_by query, ex:
|
9
|
-
# `find_by('slug' => '/about')`
|
10
|
-
delegate :find_by, to: :@cdn
|
11
|
-
|
12
5
|
def initialize(client, cache: nil)
|
13
6
|
@cdn = CDNAdapter.new(client)
|
14
7
|
@cache = cache || ActiveSupport::Cache::MemoryStore.new
|
8
|
+
@client = client
|
15
9
|
end
|
16
10
|
|
17
|
-
def find(key)
|
11
|
+
def find(key, **options)
|
18
12
|
found =
|
19
13
|
@cache.fetch(key) do
|
20
14
|
# if it's not a contentful ID don't hit the API.
|
21
15
|
# Store a nil object if we can't find the object on the CDN.
|
22
|
-
(@cdn.find(key) || nil_obj(key)) if key =~ /^\w+$/
|
16
|
+
(@cdn.find(key, options) || nil_obj(key)) if key =~ /^\w+$/
|
23
17
|
end
|
24
18
|
|
25
19
|
case found.try(:dig, 'sys', 'type')
|
@@ -30,6 +24,33 @@ module WCC::Contentful::Store
|
|
30
24
|
end
|
31
25
|
end
|
32
26
|
|
27
|
+
# TODO: https://github.com/watermarkchurch/wcc-contentful/issues/18
|
28
|
+
# figure out how to cache the results of a find_by query, ex:
|
29
|
+
# `find_by('slug' => '/about')`
|
30
|
+
def find_by(content_type:, filter: nil, options: nil)
|
31
|
+
if filter.keys == ['sys.id']
|
32
|
+
# Direct ID lookup, like what we do in `WCC::Contentful::ModelMethods.resolve`
|
33
|
+
# We can return just this item. Stores are not required to implement :include option.
|
34
|
+
if found = @cache.read(filter['sys.id'])
|
35
|
+
return found
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
q = find_all(content_type: content_type, options: { limit: 1 }.merge!(options || {}))
|
40
|
+
q = q.apply(filter) if filter
|
41
|
+
q.first
|
42
|
+
end
|
43
|
+
|
44
|
+
def find_all(content_type:, options: nil)
|
45
|
+
Query.new(
|
46
|
+
store: self,
|
47
|
+
client: @client,
|
48
|
+
relation: { content_type: content_type },
|
49
|
+
cache: @cache,
|
50
|
+
options: options
|
51
|
+
)
|
52
|
+
end
|
53
|
+
|
33
54
|
# #index is called whenever the sync API comes back with more data.
|
34
55
|
def index(json)
|
35
56
|
id = json.dig('sys', 'id')
|
@@ -41,6 +62,7 @@ module WCC::Contentful::Store
|
|
41
62
|
|
42
63
|
# we also set deletes in the cache - no need to go hit the API when we know
|
43
64
|
# this is a nil object
|
65
|
+
ensure_hash json
|
44
66
|
@cache.write(id, json)
|
45
67
|
|
46
68
|
case json.dig('sys', 'type')
|
@@ -52,6 +74,7 @@ module WCC::Contentful::Store
|
|
52
74
|
end
|
53
75
|
|
54
76
|
def set(key, value)
|
77
|
+
ensure_hash value
|
55
78
|
old = @cache.read(key)
|
56
79
|
@cache.write(key, value)
|
57
80
|
old
|
@@ -72,5 +95,67 @@ module WCC::Contentful::Store
|
|
72
95
|
}
|
73
96
|
}
|
74
97
|
end
|
98
|
+
|
99
|
+
def ensure_hash(val)
|
100
|
+
raise ArgumentError, 'Value must be a Hash' unless val.is_a?(Hash)
|
101
|
+
end
|
102
|
+
|
103
|
+
class Query < CDNAdapter::Query
|
104
|
+
def initialize(cache:, **extra)
|
105
|
+
super(cache: cache, **extra)
|
106
|
+
@cache = cache
|
107
|
+
end
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
|
+
def response
|
112
|
+
# Disabling because the superclass already took `@response`
|
113
|
+
# rubocop:disable Naming/MemoizedInstanceVariableName
|
114
|
+
@wrapped_response ||= ResponseWrapper.new(super, @cache)
|
115
|
+
# rubocop:enable Naming/MemoizedInstanceVariableName
|
116
|
+
end
|
117
|
+
|
118
|
+
ResponseWrapper =
|
119
|
+
Struct.new(:response, :cache) do
|
120
|
+
delegate :count, to: :response
|
121
|
+
|
122
|
+
def items
|
123
|
+
@items ||=
|
124
|
+
response.items.map do |item|
|
125
|
+
id = item.dig('sys', 'id')
|
126
|
+
prev = cache.read(id)
|
127
|
+
unless (prev_rev = prev&.dig('sys', 'revision')) &&
|
128
|
+
(next_rev = item.dig('sys', 'revision')) &&
|
129
|
+
next_rev < prev_rev
|
130
|
+
|
131
|
+
cache.write(id, item)
|
132
|
+
end
|
133
|
+
|
134
|
+
item
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def includes
|
139
|
+
@includes ||= IncludesWrapper.new(response, cache)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
IncludesWrapper =
|
144
|
+
Struct.new(:response, :cache) do
|
145
|
+
def [](id)
|
146
|
+
return unless item = response.includes[id]
|
147
|
+
|
148
|
+
prev = cache.read(id)
|
149
|
+
unless (prev_rev = prev&.dig('sys', 'revision')) &&
|
150
|
+
(next_rev = item.dig('sys', 'revision')) &&
|
151
|
+
next_rev < prev_rev
|
152
|
+
|
153
|
+
cache.write(id, item)
|
154
|
+
end
|
155
|
+
|
156
|
+
item
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
75
160
|
end
|
76
161
|
end
|
@@ -9,6 +9,7 @@ module WCC::Contentful::Store
|
|
9
9
|
|
10
10
|
def set(key, value)
|
11
11
|
value = value.deep_dup.freeze
|
12
|
+
ensure_hash value
|
12
13
|
mutex.with_write_lock do
|
13
14
|
old = @hash[key]
|
14
15
|
@hash[key] = value
|
@@ -26,43 +27,47 @@ module WCC::Contentful::Store
|
|
26
27
|
mutex.with_read_lock { @hash.keys }
|
27
28
|
end
|
28
29
|
|
29
|
-
def find(key)
|
30
|
+
def find(key, **_options)
|
30
31
|
mutex.with_read_lock do
|
31
32
|
@hash[key]
|
32
33
|
end
|
33
34
|
end
|
34
35
|
|
35
|
-
def find_all(content_type:)
|
36
|
+
def find_all(content_type:, options: nil)
|
36
37
|
relation = mutex.with_read_lock { @hash.values }
|
37
38
|
|
38
39
|
relation =
|
39
40
|
relation.reject do |v|
|
40
|
-
value_content_type = v.dig
|
41
|
+
value_content_type = v.try(:dig, 'sys', 'contentType', 'sys', 'id')
|
41
42
|
value_content_type.nil? || value_content_type != content_type
|
42
43
|
end
|
43
|
-
Query.new(relation)
|
44
|
+
Query.new(self, relation, options)
|
44
45
|
end
|
45
46
|
|
46
47
|
class Query < Base::Query
|
47
48
|
def result
|
48
|
-
@relation.dup
|
49
|
+
return @relation.dup unless @options[:include]
|
50
|
+
|
51
|
+
@relation.map { |e| resolve_includes(e, @options[:include]) }
|
49
52
|
end
|
50
53
|
|
51
|
-
def initialize(relation)
|
54
|
+
def initialize(store, relation, options = nil)
|
55
|
+
super(store)
|
52
56
|
@relation = relation
|
57
|
+
@options = options || {}
|
53
58
|
end
|
54
59
|
|
55
60
|
def eq(field, expected, context = nil)
|
56
61
|
locale = context[:locale] if context.present?
|
57
62
|
locale ||= 'en-US'
|
58
|
-
Query.new(@relation.select do |v|
|
63
|
+
Query.new(@store, @relation.select do |v|
|
59
64
|
val = v.dig('fields', field, locale)
|
60
65
|
if val.is_a? Array
|
61
66
|
val.include?(expected)
|
62
67
|
else
|
63
68
|
val == expected
|
64
69
|
end
|
65
|
-
end)
|
70
|
+
end, @options)
|
66
71
|
end
|
67
72
|
end
|
68
73
|
end
|
@@ -5,7 +5,7 @@ require 'pg'
|
|
5
5
|
|
6
6
|
module WCC::Contentful::Store
|
7
7
|
class PostgresStore < Base
|
8
|
-
def initialize(connection_options = nil)
|
8
|
+
def initialize(_config = nil, connection_options = nil)
|
9
9
|
super()
|
10
10
|
connection_options ||= { dbname: 'postgres' }
|
11
11
|
@conn = PG.connect(connection_options)
|
@@ -13,8 +13,10 @@ module WCC::Contentful::Store
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def set(key, value)
|
16
|
+
ensure_hash value
|
16
17
|
result = @conn.exec_prepared('upsert_entry', [key, value.to_json])
|
17
18
|
return if result.num_tuples == 0
|
19
|
+
|
18
20
|
val = result.getvalue(0, 0)
|
19
21
|
JSON.parse(val) if val
|
20
22
|
end
|
@@ -29,30 +31,36 @@ module WCC::Contentful::Store
|
|
29
31
|
def delete(key)
|
30
32
|
result = @conn.exec_prepared('delete_by_id', [key])
|
31
33
|
return if result.num_tuples == 0
|
34
|
+
|
32
35
|
JSON.parse(result.getvalue(0, 1))
|
33
36
|
end
|
34
37
|
|
35
|
-
def find(key)
|
38
|
+
def find(key, **_options)
|
36
39
|
result = @conn.exec_prepared('select_entry', [key])
|
37
40
|
return if result.num_tuples == 0
|
41
|
+
|
38
42
|
JSON.parse(result.getvalue(0, 1))
|
39
43
|
end
|
40
44
|
|
41
|
-
def find_all(content_type:)
|
45
|
+
def find_all(content_type:, options: nil)
|
42
46
|
statement = "WHERE data->'sys'->'contentType'->'sys'->>'id' = $1"
|
43
47
|
Query.new(
|
48
|
+
self,
|
44
49
|
@conn,
|
45
50
|
statement,
|
46
|
-
[content_type]
|
51
|
+
[content_type],
|
52
|
+
options
|
47
53
|
)
|
48
54
|
end
|
49
55
|
|
50
56
|
class Query < Base::Query
|
51
|
-
def initialize(conn, statement = nil, params = nil)
|
57
|
+
def initialize(store, conn, statement = nil, params = nil, options = nil)
|
58
|
+
super(store)
|
52
59
|
@conn = conn
|
53
60
|
@statement = statement ||
|
54
61
|
"WHERE data->'sys'->>'id' IS NOT NULL"
|
55
62
|
@params = params || []
|
63
|
+
@options = options || {}
|
56
64
|
end
|
57
65
|
|
58
66
|
def eq(field, expected, context = nil)
|
@@ -65,14 +73,17 @@ module WCC::Contentful::Store
|
|
65
73
|
"->$#{push_param(locale, params)} ? $#{push_param(expected, params)}"
|
66
74
|
|
67
75
|
Query.new(
|
76
|
+
@store,
|
68
77
|
@conn,
|
69
78
|
statement,
|
70
|
-
params
|
79
|
+
params,
|
80
|
+
@options
|
71
81
|
)
|
72
82
|
end
|
73
83
|
|
74
84
|
def count
|
75
85
|
return @count if @count
|
86
|
+
|
76
87
|
statement = 'SELECT count(*) FROM contentful_raw ' + @statement
|
77
88
|
result = @conn.exec(statement, @params)
|
78
89
|
@count = result.getvalue(0, 0).to_i
|
@@ -80,27 +91,49 @@ module WCC::Contentful::Store
|
|
80
91
|
|
81
92
|
def first
|
82
93
|
return @first if @first
|
94
|
+
|
83
95
|
statement = 'SELECT * FROM contentful_raw ' + @statement + ' LIMIT 1'
|
84
96
|
result = @conn.exec(statement, @params)
|
85
|
-
|
97
|
+
return if result.num_tuples == 0
|
98
|
+
|
99
|
+
resolve_includes(
|
100
|
+
JSON.parse(result.getvalue(0, 1)),
|
101
|
+
@options[:include]
|
102
|
+
)
|
86
103
|
end
|
87
104
|
|
88
105
|
def map
|
89
106
|
arr = []
|
90
|
-
resolve.each
|
107
|
+
resolve.each do |row|
|
108
|
+
arr << yield(
|
109
|
+
resolve_includes(
|
110
|
+
JSON.parse(row['data']),
|
111
|
+
@options[:include]
|
112
|
+
)
|
113
|
+
)
|
114
|
+
end
|
91
115
|
arr
|
92
116
|
end
|
93
117
|
|
94
118
|
def result
|
95
119
|
arr = []
|
96
|
-
resolve.each
|
120
|
+
resolve.each do |row|
|
121
|
+
arr <<
|
122
|
+
resolve_includes(
|
123
|
+
JSON.parse(row['data']),
|
124
|
+
@options[:include]
|
125
|
+
)
|
126
|
+
end
|
97
127
|
arr
|
98
128
|
end
|
99
129
|
|
130
|
+
# TODO: override resolve_includes to make it more efficient
|
131
|
+
|
100
132
|
private
|
101
133
|
|
102
134
|
def resolve
|
103
135
|
return @resolved if @resolved
|
136
|
+
|
104
137
|
statement = 'SELECT * FROM contentful_raw ' + @statement
|
105
138
|
@resolved = @conn.exec(statement, @params)
|
106
139
|
end
|
@@ -120,7 +153,7 @@ module WCC::Contentful::Store
|
|
120
153
|
CREATE INDEX IF NOT EXISTS contentful_raw_value_type ON contentful_raw ((data->'sys'->>'type'));
|
121
154
|
CREATE INDEX IF NOT EXISTS contentful_raw_value_content_type ON contentful_raw ((data->'sys'->'contentType'->'sys'->>'id'));
|
122
155
|
|
123
|
-
DROP FUNCTION IF EXISTS "upsert_entry";
|
156
|
+
DROP FUNCTION IF EXISTS "upsert_entry"(_id varchar, _data jsonb);
|
124
157
|
CREATE FUNCTION "upsert_entry"(_id varchar, _data jsonb) RETURNS jsonb AS $$
|
125
158
|
DECLARE
|
126
159
|
prev jsonb;
|
@@ -133,7 +166,7 @@ module WCC::Contentful::Store
|
|
133
166
|
RETURN prev;
|
134
167
|
END;
|
135
168
|
$$ LANGUAGE 'plpgsql';
|
136
|
-
HEREDOC
|
169
|
+
HEREDOC
|
137
170
|
)
|
138
171
|
|
139
172
|
conn.prepare('upsert_entry', 'SELECT * FROM upsert_entry($1,$2)')
|