wcc-contentful 0.2.2 → 0.3.0.pre.rc
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/.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)')
|