wcc-contentful 0.4.0.pre.alpha → 1.0.0.pre.rc3
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 +5 -5
- data/Guardfile +43 -0
- data/README.md +246 -11
- data/Rakefile +5 -0
- data/app/controllers/wcc/contentful/webhook_controller.rb +25 -24
- data/app/jobs/wcc/contentful/webhook_enable_job.rb +36 -2
- data/config/routes.rb +1 -1
- data/doc +1 -0
- data/lib/tasks/download_schema.rake +12 -0
- data/lib/wcc/contentful.rb +70 -16
- data/lib/wcc/contentful/active_record_shim.rb +72 -0
- data/lib/wcc/contentful/configuration.rb +177 -46
- data/lib/wcc/contentful/content_type_indexer.rb +14 -0
- data/lib/wcc/contentful/downloads_schema.rb +112 -0
- data/lib/wcc/contentful/engine.rb +33 -14
- data/lib/wcc/contentful/event.rb +171 -0
- data/lib/wcc/contentful/events.rb +41 -0
- data/lib/wcc/contentful/exceptions.rb +3 -0
- data/lib/wcc/contentful/indexed_representation.rb +2 -2
- data/lib/wcc/contentful/instrumentation.rb +31 -0
- data/lib/wcc/contentful/link.rb +28 -0
- data/lib/wcc/contentful/link_visitor.rb +122 -0
- data/lib/wcc/contentful/middleware.rb +7 -0
- data/lib/wcc/contentful/middleware/store.rb +158 -0
- data/lib/wcc/contentful/middleware/store/caching_middleware.rb +114 -0
- data/lib/wcc/contentful/model.rb +37 -3
- data/lib/wcc/contentful/model_builder.rb +1 -0
- data/lib/wcc/contentful/model_methods.rb +40 -15
- data/lib/wcc/contentful/model_singleton_methods.rb +47 -30
- data/lib/wcc/contentful/rake.rb +4 -0
- data/lib/wcc/contentful/rspec.rb +46 -0
- data/lib/wcc/contentful/services.rb +61 -27
- data/lib/wcc/contentful/simple_client.rb +81 -25
- data/lib/wcc/contentful/simple_client/management.rb +43 -10
- data/lib/wcc/contentful/simple_client/response.rb +61 -22
- data/lib/wcc/contentful/simple_client/typhoeus_adapter.rb +17 -17
- data/lib/wcc/contentful/store.rb +7 -66
- data/lib/wcc/contentful/store/README.md +85 -0
- data/lib/wcc/contentful/store/base.rb +34 -119
- data/lib/wcc/contentful/store/cdn_adapter.rb +71 -12
- data/lib/wcc/contentful/store/factory.rb +186 -0
- data/lib/wcc/contentful/store/instrumentation.rb +55 -0
- data/lib/wcc/contentful/store/interface.rb +82 -0
- data/lib/wcc/contentful/store/memory_store.rb +27 -24
- data/lib/wcc/contentful/store/postgres_store.rb +268 -101
- data/lib/wcc/contentful/store/postgres_store/schema_1.sql +73 -0
- data/lib/wcc/contentful/store/postgres_store/schema_2.sql +21 -0
- data/lib/wcc/contentful/store/query.rb +246 -0
- data/lib/wcc/contentful/store/query/interface.rb +63 -0
- data/lib/wcc/contentful/store/rspec_examples.rb +48 -0
- data/lib/wcc/contentful/store/rspec_examples/basic_store.rb +629 -0
- data/lib/wcc/contentful/store/rspec_examples/include_param.rb +283 -0
- data/lib/wcc/contentful/store/rspec_examples/nested_queries.rb +342 -0
- data/lib/wcc/contentful/sync_engine.rb +181 -0
- data/lib/wcc/contentful/test.rb +7 -0
- data/lib/wcc/contentful/test/attributes.rb +56 -0
- data/lib/wcc/contentful/test/double.rb +76 -0
- data/lib/wcc/contentful/test/factory.rb +101 -0
- data/lib/wcc/contentful/version.rb +1 -1
- data/wcc-contentful.gemspec +23 -11
- metadata +299 -116
- data/Gemfile +0 -6
- data/app/jobs/wcc/contentful/delayed_sync_job.rb +0 -63
- data/lib/wcc/contentful/client_ext.rb +0 -28
- data/lib/wcc/contentful/graphql.rb +0 -14
- data/lib/wcc/contentful/graphql/builder.rb +0 -177
- data/lib/wcc/contentful/graphql/types.rb +0 -54
- data/lib/wcc/contentful/simple_client/http_adapter.rb +0 -24
- data/lib/wcc/contentful/store/lazy_cache_store.rb +0 -161
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b5cae24e96be56167418f05f625fdede6e0f4bfe0c9a87265b4098bf6906a6ca
|
4
|
+
data.tar.gz: ddad1d967c0e181cd3ecd97ab571f0e05a5228e158deefb6edf81c653750e99e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7ff892d606377aafec3529eb45c1bac84ba7e2b3c877eacbccd09ec6ea5331d60db6afacaf7152e0716ea9da7ec8864e61a937f954873992428353bd7179e916
|
7
|
+
data.tar.gz: 6c22be5cc52e788dfa5e5536b76b855508b27230c7c6120ecb10e23b6a7e4b190470ffc7ec2a5b81f0fac57874047130a85e15ab561cc90a691afb4e1116dcd7
|
data/Guardfile
CHANGED
@@ -3,6 +3,39 @@
|
|
3
3
|
|
4
4
|
# To run, use `bundle exec guard`.
|
5
5
|
|
6
|
+
def watch_async(regexp)
|
7
|
+
raise ArgumentError, "No block given" unless block_given?
|
8
|
+
match_queue = Queue.new
|
9
|
+
|
10
|
+
watch(regexp) do |match|
|
11
|
+
# Producer - add matches to the match queue
|
12
|
+
match_queue << match
|
13
|
+
nil
|
14
|
+
end
|
15
|
+
|
16
|
+
# Consumer - process matches as a batch
|
17
|
+
Thread.new do
|
18
|
+
loop do
|
19
|
+
matches = []
|
20
|
+
matches << match_queue.pop
|
21
|
+
|
22
|
+
loop do
|
23
|
+
begin
|
24
|
+
matches << match_queue.pop(true)
|
25
|
+
rescue ThreadError
|
26
|
+
break
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
begin
|
31
|
+
yield matches if matches.length > 0
|
32
|
+
rescue StandardError => ex
|
33
|
+
STDERR.puts "Error! #{ex}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
6
39
|
group :red_green_refactor, halt_on_fail: true do
|
7
40
|
guard :rspec, cmd: 'bundle exec rspec' do
|
8
41
|
require 'guard/rspec/dsl'
|
@@ -46,6 +79,16 @@ group :red_green_refactor, halt_on_fail: true do
|
|
46
79
|
watch(%r{.+\.rb$})
|
47
80
|
watch(%r{(?:.+/)?\.rubocop(?:_todo)?\.yml$}) { |m| File.dirname(m[0]) }
|
48
81
|
end
|
82
|
+
|
83
|
+
guard :shell, all_on_start: false do
|
84
|
+
watch_async(%r{app/views/(.+\.html.*\.erb)}) { |matches|
|
85
|
+
|
86
|
+
matches = matches.map { |m| File.absolute_path(m[0]) }
|
87
|
+
Dir.chdir('..') {
|
88
|
+
system("bundle exec erblint #{matches.join(' ')}")
|
89
|
+
}
|
90
|
+
}
|
91
|
+
end
|
49
92
|
end
|
50
93
|
|
51
94
|
group :autofix do
|
data/README.md
CHANGED
@@ -1,11 +1,93 @@
|
|
1
|
-
[](https://
|
2
|
-
[](https://rubygems.org/gems/wcc-contentful)
|
2
|
+
[](https://travis-ci.org/watermarkchurch/wcc-contentful)
|
3
3
|
[](https://coveralls.io/github/watermarkchurch/wcc-contentful?branch=master)
|
4
4
|
|
5
|
-
Full documentation: https://
|
5
|
+
Full documentation: https://watermarkchurch.github.io/wcc-contentful/latest/wcc-contentful/
|
6
6
|
|
7
7
|
# WCC::Contentful
|
8
8
|
|
9
|
+
An alternative to Contentful's [contentful.rb ruby client](https://github.com/contentful/contentful.rb/), [contentful_model](https://github.com/contentful/contentful_model), and [contentful_rails](https://github.com/contentful/contentful_rails) gems all in one.
|
10
|
+
|
11
|
+
Table of Contents:
|
12
|
+
|
13
|
+
1. [Why?](#why-did-you-rewrite-the-contentful-ruby-stack)
|
14
|
+
2. [Installation](#installation)
|
15
|
+
|
16
|
+
## Why did you rewrite the Contentful ruby stack?
|
17
|
+
|
18
|
+
We started working with Contentful almost 3 years ago. Since that time, Contentful's ruby stack has improved, but there are still a number of pain points that we feel we have addressed better with our gem. These are:
|
19
|
+
|
20
|
+
* [Low-level caching](#low-level-caching)
|
21
|
+
* [Better integration with Rails & Rails models](#better-rails-integration)
|
22
|
+
* [Automatic pagination and Automatic link resolution](#automatic-pagination-and-link-resolution)
|
23
|
+
* [Automatic webhook management](#automatic-webhook-management)
|
24
|
+
|
25
|
+
Our gem no longer depends on any of the Contentful gems and interacts directly with the [Contentful CDA](https://www.contentful.com/developers/docs/references/content-delivery-api/) and [Content Management API](https://www.contentful.com/developers/docs/references/content-management-api/) over HTTPS.
|
26
|
+
|
27
|
+
### Low-level caching
|
28
|
+
|
29
|
+
The wcc-contentful gem enables caching at two levels: the HTTP response using [Faraday HTTP cache middleware](https://github.com/sourcelevel/faraday-http-cache), and at the Entry level using the Rails cache and the [Sync API](https://www.contentful.com/developers/docs/references/content-delivery-api/#/reference/synchronization) to keep it up to date. We've found these two cache layers to be very effective at reducing both round trip latency to the Content Delivery API, as well as reducing our monthly API request usage. (which reduces our overage charges. Hooray!)
|
30
|
+
|
31
|
+
#### At the request/response level
|
32
|
+
By default, the contentful.rb gem requires the [HTTP library](https://rubygems.org/gems/http). While simple and straightforward to use, it is not as powerful for caching. We decided to make our client conform to the [Faraday gem's API](https://github.com/lostisland/faraday). If you prefer not to use Faraday, you can choose to supply your own HTTP adapter that "quacks like" Faraday (see the [TyphoeusAdapter](https://github.com/watermarkchurch/wcc-contentful/blob/master/wcc-contentful/lib/wcc/contentful/simple_client/typhoeus_adapter.rb) for one implementation).
|
33
|
+
|
34
|
+
Using Faraday makes it easy to add Middleware. As an example, our flagship Rails app that powers watermark.org uses the following configuration in Production, which provides us with instrumentation through statsd, logging, and caching:
|
35
|
+
```rb
|
36
|
+
config.connection = Faraday.new do |builder|
|
37
|
+
builder.use :http_cache,
|
38
|
+
shared_cache: false,
|
39
|
+
store: ActiveSupport::Cache::MemoryStore.new(size: 512.megabytes),
|
40
|
+
logger: Rails.logger,
|
41
|
+
serializer: Marshal,
|
42
|
+
instrumenter: ActiveSupport::Notifications
|
43
|
+
|
44
|
+
builder.use :gzip
|
45
|
+
builder.response :logger, Rails.logger, headers: false, bodies: false if Rails.env.development?
|
46
|
+
builder.request :instrumentation
|
47
|
+
builder.adapter :typhoeus
|
48
|
+
end
|
49
|
+
```
|
50
|
+
|
51
|
+
#### At the Entry level
|
52
|
+
|
53
|
+
Our stack has three layers, the middle layer being essentially a cache for individual Entry hashes parsed out of responses from the Delivery API. We were able to add a caching layer here which stores entries retrieved over the Sync API, and responds to queries with cached versions of local content when possible. We consider this to be our best innovation on the Contentful ruby stack.
|
54
|
+
|
55
|
+
We have successfully created caching layers using Memcached, Postgres, and an in-memory hash. The architecture allows other caching implementations to be created fairly easily, and we have a set of rspec specs that can verify that a cache store behaves appropriately. For more information, [see the documentation on the caching modes here](https://watermarkchurch.github.io/wcc-contentful/latest/wcc-contentful/WCC/Contentful/Store.html).
|
56
|
+
|
57
|
+
### Better Rails Integration
|
58
|
+
|
59
|
+
When we initially got started with the Contentful ruby models, we encountered one problem that was more frustrating than all others: If a field exists in the content model, but the particular entry we're working with does not have that field populated, then accessing that field raised a `NoMethodError`. This caused us to litter our code with `if defined?(entry.my_field)` which is bad practice. (Note: this has since been fixed in contentful.rb v2).
|
60
|
+
|
61
|
+
We decided it was better to not rely on `method_missing?` (what contentful.rb does), and instead to use `define_method` in an initializer to generate the methods for our models. This has the advantage that calling `.instance_methods` on a model class includes all the fields present in the content model.
|
62
|
+
|
63
|
+
We also took advantage of Rails' naming conventions to automatically infer the content type name based on the class name. Thus in our code, we have `app/models/page.rb` which defines `class Page << WCC::Contentful::Model::Page`, and is automatically linked to the `page` content type ID. (Note: this is overridable on a per-model basis)
|
64
|
+
|
65
|
+
All our models are automatically generated at startup which improves response times at the expense of initialization time. In addition, our content model registry allows easy definition of custom models in your `app/models` directory to override fields. This plays nice with other gems like algoliasearch-rails, which allows you to declaratively manage your Algolia indexes. Another example from our flagship watermark.org:
|
66
|
+
|
67
|
+
```rb
|
68
|
+
class Page < WCC::Contentful::Model::Page
|
69
|
+
include AlgoliaSearch
|
70
|
+
|
71
|
+
algoliasearch(index_name: 'pages') do
|
72
|
+
attribute(:title, :slug)
|
73
|
+
...
|
74
|
+
end
|
75
|
+
```
|
76
|
+
|
77
|
+
### Automatic Pagination and Link Resolution
|
78
|
+
|
79
|
+
Using the `contentful_model` gem, calling `Page.all.load` does not give you all Page entries if there are more than 100. To get the next page you must call `.paginate` on the response. By contrast, `Page.find_all` in the `wcc-contentful` gem gives you a [Lazy Enumerator](https://ruby-doc.org/core-2.5.0/Enumerator/Lazy.html). As you iterate past the 100th entry, the enumerator will automatically fetch the next page. If you only enumerate 99 entries (say with `.take(99)`), then the second page will never be fetched.
|
80
|
+
|
81
|
+
Similarly, if your Page references an asset, say `hero_image`, that field returns a `Link` object rather than the actual `Asset`. You must either predefine how many links you need using `Page.load_children(3).all.load`, or detect that `hero_image` is a `Link` like `if @page.hero_image.is_a? Contentful::Link` and then call `.resolve` on the link. We found all of that to be too cumbersome when we are down in a nested partial view template that may be invoked from multiple places.
|
82
|
+
|
83
|
+
The `wcc-contentful` gem, by contrast, automatically resolves a link when accessing the associated attribute. So in our example above, `wcc-contentful` will **always** return a `WCC::Contentful::Asset` when calling `@page.hero_image`, even if it has to execute a query to cdn.contentful.com in order to fetch it.
|
84
|
+
|
85
|
+
Warning: This can easily lead to you exhausting your Contentful API quota if you do not carefully tune your cache, which you should be doing anyways! The default settings will use the Rails cache to try to cache these resolutions, but *you are ultimately responsible for how many queries you execute!*
|
86
|
+
|
87
|
+
### Automatic webhook management
|
88
|
+
|
89
|
+
The `wcc-contentful` gem, just like `contentful_rails`, provides an Engine to be mounted in your Rails routes file. Unlike `contentful_rails`, if you also configure `wcc-contentful` with a Contentful Management Token and a public `app_url`, then on startup the `wcc-contentful` engine will reach out to the Contentful Management API and ensure that a webhook is configured to point to your app. This is one less devops burden on you, and plays very nicely in with Heroku review apps.
|
90
|
+
|
9
91
|
## Installation
|
10
92
|
|
11
93
|
Add this line to your application's Gemfile:
|
@@ -14,17 +96,30 @@ Add this line to your application's Gemfile:
|
|
14
96
|
gem 'wcc-contentful', require: 'wcc/contentful/rails'
|
15
97
|
```
|
16
98
|
|
99
|
+
If you're not using rails, exclude the `require:` parameter.
|
100
|
+
|
101
|
+
```ruby
|
102
|
+
gem 'wcc-contentful'
|
103
|
+
```
|
104
|
+
|
17
105
|
And then execute:
|
18
106
|
|
19
|
-
|
107
|
+
```
|
108
|
+
$ bundle
|
109
|
+
```
|
20
110
|
|
21
|
-
Or install it yourself
|
111
|
+
Or install it yourself:
|
22
112
|
|
23
|
-
|
113
|
+
```
|
114
|
+
$ gem install wcc-contentful
|
115
|
+
```
|
24
116
|
|
25
117
|
## Configure
|
26
118
|
|
119
|
+
Put this in an initializer:
|
120
|
+
|
27
121
|
```ruby
|
122
|
+
# config/initializers/wcc_contentful.rb
|
28
123
|
WCC::Contentful.configure do |config|
|
29
124
|
config.access_token = <CONTENTFUL_ACCESS_TOKEN>
|
30
125
|
config.space = <CONTENTFUL_SPACE_ID>
|
@@ -33,13 +128,16 @@ end
|
|
33
128
|
WCC::Contentful.init!
|
34
129
|
```
|
35
130
|
|
131
|
+
All configuration options can be found [in the rubydoc under
|
132
|
+
WCC::Contentful::Configuration](https://watermarkchurch.github.io/wcc-contentful/latest/wcc-contentful/WCC/Contentful/Configuration)
|
133
|
+
|
36
134
|
## Usage
|
37
135
|
|
38
136
|
### WCC::Contentful::Model API
|
39
137
|
|
40
138
|
The WCC::Contentful::Model API exposes Contentful data as a set of dynamically
|
41
139
|
generated Ruby objects. These objects are based on the content types in your
|
42
|
-
Contentful space. All these objects are generated by WCC::Contentful.init
|
140
|
+
Contentful space. All these objects are generated by `WCC::Contentful.init!`
|
43
141
|
|
44
142
|
The following examples show how to use this API to find entries of the `page`
|
45
143
|
content type:
|
@@ -164,7 +262,8 @@ response.includes
|
|
164
262
|
|
165
263
|
The client handles Paging automatically within the lazy iterator returned by #items.
|
166
264
|
This lazy iterator does not respect the `limit` param - that param is only passed
|
167
|
-
through to the API to set the page size.
|
265
|
+
through to the API to set the page size. If you truly want a limited subset of
|
266
|
+
response items, use [`response.items.take(n)`](https://ruby-doc.org/core-2.5.3/Enumerable.html#method-i-take)
|
168
267
|
|
169
268
|
Entries included via the `include` parameter are made available on the #includes
|
170
269
|
field. This is a hash of `<entry ID> => <raw entry>` and makes it easy to grab
|
@@ -211,11 +310,147 @@ class MyJob < ApplicationJob
|
|
211
310
|
end
|
212
311
|
```
|
213
312
|
|
214
|
-
##
|
313
|
+
## Architecture
|
215
314
|
|
216
|
-
|
315
|
+

|
316
|
+
|
317
|
+
## Test Helpers
|
318
|
+
|
319
|
+
To use the test helpers, include the following in your rails_helper.rb:
|
320
|
+
|
321
|
+
```ruby
|
322
|
+
require 'wcc/contentful/rspec'
|
323
|
+
```
|
324
|
+
|
325
|
+
This adds the following helpers to all your specs:
|
326
|
+
|
327
|
+
```ruby
|
328
|
+
##
|
329
|
+
# Builds a in-memory instance of the Contentful model for the given content_type.
|
330
|
+
# All attributes that are known to be required fields on the content type
|
331
|
+
# will return a default value based on the field type.
|
332
|
+
instance = contentful_create('my-content-type', my_field: 'some-value')
|
333
|
+
# => #<WCC::Contentful::Model::MyContentType:0x0000000005c71a78 @created_at=2018-04-16 18:41:17 UTC...>
|
334
|
+
|
335
|
+
instance.my_field
|
336
|
+
# => "some-value"
|
337
|
+
|
338
|
+
instance.other_required_field
|
339
|
+
# => "default-value"
|
340
|
+
|
341
|
+
instance.other_optional_field
|
342
|
+
# => nil
|
343
|
+
|
344
|
+
instance.not_a_field
|
345
|
+
# NoMethodError: undefined method `not_a_field' for #<MyContentType:0x00007fbac81ee490>
|
346
|
+
|
347
|
+
##
|
348
|
+
# Builds a rspec double of the Contentful model for the given content_type.
|
349
|
+
# All attributes that are known to be required fields on the content type
|
350
|
+
# will return a default value based on the field type.
|
351
|
+
dbl = contentful_double('my-content-type', my_field: 'other-value')
|
352
|
+
# => #<Double (anonymous)>
|
353
|
+
|
354
|
+
dbl.my_field
|
355
|
+
# => "other-value"
|
356
|
+
|
357
|
+
dbl.other_optional_field
|
358
|
+
# => nil
|
359
|
+
|
360
|
+
dbl.not_a_field
|
361
|
+
# => #<Double (anonymous)> received unexpected message :not_a_field with (no args)
|
362
|
+
|
363
|
+
##
|
364
|
+
# Builds out a fake Contentful entry for the given content type, and then
|
365
|
+
# stubs the Model API to return that content type for `.find` and `.find_by`
|
366
|
+
# query methods.
|
367
|
+
stubbed = contentful_stub('my-content-type', id: '1234', my_field: 'test')
|
368
|
+
|
369
|
+
WCC::Contentful::Model.find('1234') == stubbed
|
370
|
+
# => true
|
371
|
+
|
372
|
+
MyContentType.find('1234') == stubbed
|
373
|
+
# => true
|
374
|
+
|
375
|
+
MyContentType.find_by(my_field: 'test') == stubbed
|
376
|
+
# => true
|
377
|
+
```
|
378
|
+
|
379
|
+
## Advanced Configuration Example
|
380
|
+
|
381
|
+
Here's an example containing all the configuration options, and a sample setup for
|
382
|
+
automatic deployment to Heroku. This is intended to make you aware of what is possible,
|
383
|
+
and not as a general recommendation of what your setup should look like.
|
384
|
+
|
385
|
+
```ruby
|
386
|
+
# config/initializers/wcc_contentful.rb
|
387
|
+
WCC::Contentful.configure do |config|
|
388
|
+
config.access_token = ENV['CONTENTFUL_ACCESS_TOKEN']
|
389
|
+
config.space = ENV['CONTENTFUL_SPACE_ID']
|
390
|
+
config.environment = ENV['CONTENTFUL_ENVIRONMENT']
|
391
|
+
config.preview_token = ENV['CONTENTFUL_PREVIEW_ACCESS_TOKEN']
|
392
|
+
|
393
|
+
# You may or may not want to provide this to your production server...
|
394
|
+
config.management_token = ENV['CONTENTFUL_MANAGEMENT_TOKEN'] unless Rails.env.production?
|
395
|
+
|
396
|
+
config.app_url = "https://#{ENV['HOSTNAME']}"
|
397
|
+
config.webhook_username = 'my-app-webhook'
|
398
|
+
config.webhook_password = Rails.application.secrets.webhook_password
|
399
|
+
config.webhook_jobs << MyOnWebhookJob
|
400
|
+
|
401
|
+
config.store = :lazy_sync, Rails.cache if Rails.env.production?
|
402
|
+
# config.store = MyCustomStore.new
|
403
|
+
|
404
|
+
# Use a custom Faraday connection
|
405
|
+
config.connection = Faraday.new do |builder|
|
406
|
+
f.request :retry
|
407
|
+
f.request MyFaradayRequestAdapter.new
|
408
|
+
...
|
409
|
+
end
|
410
|
+
# OR implement some adapter like this to use another HTTP client
|
411
|
+
config.connection = MyNetHttpAdapter.new
|
412
|
+
|
413
|
+
config.update_schema_file = :never
|
414
|
+
end
|
415
|
+
|
416
|
+
WCC::Contentful.init!
|
417
|
+
```
|
418
|
+
|
419
|
+
For Heroku:
|
420
|
+
|
421
|
+
```yaml
|
422
|
+
# Procfile
|
423
|
+
web: bundle exec rails s
|
424
|
+
worker: bundle exec sidekiq
|
425
|
+
release: bin/release
|
426
|
+
```
|
427
|
+
|
428
|
+
```sh
|
429
|
+
# bin/release
|
430
|
+
#!/bin/sh
|
431
|
+
|
432
|
+
set -e
|
433
|
+
|
434
|
+
echo "Migrating database..."
|
435
|
+
bin/rake db:migrate
|
436
|
+
|
437
|
+
echo "Migrating contentful..."
|
438
|
+
migrations_to_be_run=$( ... ) # somehow figure this out
|
439
|
+
node_modules/.bin/contentful-migration \
|
440
|
+
-s $CONTENTFUL_SPACE_ID -a $CONTENTFUL_MANAGEMENT_TOKEN \
|
441
|
+
-y -p "$migrations_to_be_run"
|
442
|
+
|
443
|
+
echo "Updating schema file..."
|
444
|
+
rake wcc_contentful:download_schema
|
445
|
+
```
|
446
|
+
|
447
|
+
All configuration options can be found [in the rubydoc](https://www.rubydoc.info/gems/wcc-contentful/WCC/Contentful/Configuration) under
|
448
|
+
{WCC::Contentful::Configuration}
|
449
|
+
|
450
|
+
|
451
|
+
## Development
|
217
452
|
|
218
|
-
|
453
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
219
454
|
|
220
455
|
## Contributing
|
221
456
|
|
data/Rakefile
ADDED
@@ -8,6 +8,7 @@ module WCC::Contentful
|
|
8
8
|
# the jobs configured in {WCC::Contentful::Configuration WCC::Contentful::Configuration#webhook_jobs}
|
9
9
|
class WebhookController < ApplicationController
|
10
10
|
include WCC::Contentful::ServiceAccessors
|
11
|
+
include Wisper::Publisher
|
11
12
|
|
12
13
|
before_action :authorize_contentful
|
13
14
|
protect_from_forgery unless: -> { request.format.json? }
|
@@ -17,27 +18,17 @@ module WCC::Contentful
|
|
17
18
|
end
|
18
19
|
|
19
20
|
def receive
|
20
|
-
|
21
|
-
|
22
|
-
event =
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
elsif job.respond_to?(:call)
|
32
|
-
job.call(event)
|
33
|
-
else
|
34
|
-
Rails.logger.error "Misconfigured webhook job: #{job} does not respond to " \
|
35
|
-
':perform_later or :call'
|
36
|
-
end
|
37
|
-
rescue StandardError => e
|
38
|
-
Rails.logger.error "Error in job #{job}: #{e}"
|
39
|
-
end
|
40
|
-
end
|
21
|
+
params.require('sys').require(%w[id type])
|
22
|
+
params.permit('sys', 'fields')
|
23
|
+
event = params.slice('sys', 'fields').permit!.to_h
|
24
|
+
|
25
|
+
return unless check_environment(event)
|
26
|
+
|
27
|
+
# Immediately update the store, we may update again later using SyncEngine::Job.
|
28
|
+
store.index(event) if store.index?
|
29
|
+
|
30
|
+
event = WCC::Contentful::Event.from_raw(event, source: self)
|
31
|
+
emit_event(event)
|
41
32
|
end
|
42
33
|
|
43
34
|
private
|
@@ -62,9 +53,19 @@ module WCC::Contentful
|
|
62
53
|
render json: { msg: 'This endpoint only responds to webhooks from Contentful' }, status: 406
|
63
54
|
end
|
64
55
|
|
65
|
-
def
|
66
|
-
|
67
|
-
|
56
|
+
def check_environment(event)
|
57
|
+
environment_id = event.dig('sys', 'environment', 'sys', 'id')
|
58
|
+
return true unless environment_id.present?
|
59
|
+
|
60
|
+
configured_environment = WCC::Contentful.configuration.environment.presence || 'master'
|
61
|
+
configured_environment.casecmp(environment_id) == 0
|
62
|
+
end
|
63
|
+
|
64
|
+
def emit_event(event)
|
65
|
+
type = event.dig('sys', 'type')
|
66
|
+
raise ArgumentError, "Unknown event type #{event}" unless type.present?
|
67
|
+
|
68
|
+
broadcast(type, event)
|
68
69
|
end
|
69
70
|
end
|
70
71
|
end
|