wcc-contentful 1.0.6 → 1.1.1
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/README.md +174 -9
- data/app/jobs/wcc/contentful/webhook_enable_job.rb +7 -7
- data/lib/wcc/contentful/instrumentation.rb +20 -2
- data/lib/wcc/contentful/link_visitor.rb +26 -30
- data/lib/wcc/contentful/middleware/store.rb +2 -1
- data/lib/wcc/contentful/model.rb +5 -122
- data/lib/wcc/contentful/model_api.rb +182 -0
- data/lib/wcc/contentful/model_builder.rb +10 -4
- data/lib/wcc/contentful/model_methods.rb +8 -10
- data/lib/wcc/contentful/model_singleton_methods.rb +6 -6
- data/lib/wcc/contentful/rspec.rb +7 -5
- data/lib/wcc/contentful/services.rb +59 -61
- data/lib/wcc/contentful/store/cdn_adapter.rb +7 -1
- data/lib/wcc/contentful/store/factory.rb +2 -6
- data/lib/wcc/contentful/store/memory_store.rb +47 -13
- data/lib/wcc/contentful/store/query.rb +22 -2
- data/lib/wcc/contentful/store/rspec_examples/basic_store.rb +0 -103
- data/lib/wcc/contentful/store/rspec_examples/operators/eq.rb +92 -0
- data/lib/wcc/contentful/store/rspec_examples/operators/in.rb +131 -0
- data/lib/wcc/contentful/store/rspec_examples/operators/ne.rb +77 -0
- data/lib/wcc/contentful/store/rspec_examples/operators/nin.rb +80 -0
- data/lib/wcc/contentful/store/rspec_examples/operators.rb +50 -0
- data/lib/wcc/contentful/store/rspec_examples.rb +2 -0
- data/lib/wcc/contentful/sync_engine.rb +0 -1
- data/lib/wcc/contentful/test/attributes.rb +0 -4
- data/lib/wcc/contentful/test/double.rb +4 -2
- data/lib/wcc/contentful/test/factory.rb +4 -2
- data/lib/wcc/contentful/version.rb +1 -1
- data/lib/wcc/contentful.rb +14 -8
- data/wcc-contentful.gemspec +0 -5
- metadata +117 -37
data/lib/wcc/contentful.rb
CHANGED
@@ -34,7 +34,10 @@ module WCC::Contentful
|
|
34
34
|
# Gets the current configuration, after calling WCC::Contentful.configure
|
35
35
|
attr_reader :configuration
|
36
36
|
|
37
|
-
|
37
|
+
def types
|
38
|
+
ActiveSupport::Deprecation.warn('Use WCC::Contentful::Model.schema instead')
|
39
|
+
WCC::Contentful::Model.schema
|
40
|
+
end
|
38
41
|
|
39
42
|
# Gets all queryable locales.
|
40
43
|
# Reserved for future use.
|
@@ -91,7 +94,7 @@ module WCC::Contentful
|
|
91
94
|
end
|
92
95
|
end
|
93
96
|
|
94
|
-
|
97
|
+
content_types =
|
95
98
|
begin
|
96
99
|
if File.exist?(configuration.schema_file)
|
97
100
|
JSON.parse(File.read(configuration.schema_file))['contentTypes']
|
@@ -101,32 +104,35 @@ module WCC::Contentful
|
|
101
104
|
nil
|
102
105
|
end
|
103
106
|
|
104
|
-
if
|
107
|
+
if !content_types && %i[if_possible never].include?(configuration.update_schema_file)
|
105
108
|
# Final fallback - try to grab content types from CDN. We can't update the file
|
106
109
|
# because the CDN doesn't have all the field validation info, but we can at least
|
107
110
|
# build the WCC::Contentful::Model instances.
|
108
111
|
client = Services.instance.management_client ||
|
109
112
|
Services.instance.client
|
110
113
|
begin
|
111
|
-
|
114
|
+
content_types = client.content_types(limit: 1000).items if client
|
112
115
|
rescue WCC::Contentful::SimpleClient::ApiError => e
|
113
116
|
# indicates bad credentials
|
114
117
|
WCC::Contentful.logger.warn("Unable to load content types from API - #{e.message}")
|
115
118
|
end
|
116
119
|
end
|
117
120
|
|
118
|
-
unless
|
121
|
+
unless content_types
|
119
122
|
raise InitializationError, 'Unable to load content types from schema file or API!' \
|
120
123
|
' Check your access token and space ID.'
|
121
124
|
end
|
122
125
|
|
123
|
-
|
124
|
-
|
126
|
+
# Set the schema on the default WCC::Contentful::Model
|
127
|
+
WCC::Contentful::Model.configure(
|
128
|
+
configuration,
|
129
|
+
schema: WCC::Contentful::ContentTypeIndexer.from_json_schema(content_types).types,
|
130
|
+
services: WCC::Contentful::Services.instance
|
131
|
+
)
|
125
132
|
|
126
133
|
# Drop an initial sync
|
127
134
|
WCC::Contentful::SyncEngine::Job.perform_later if defined?(WCC::Contentful::SyncEngine::Job)
|
128
135
|
|
129
|
-
WCC::Contentful::ModelBuilder.new(@types).build_models
|
130
136
|
@configuration = @configuration.freeze
|
131
137
|
@initialized = true
|
132
138
|
end
|
data/wcc-contentful.gemspec
CHANGED
@@ -24,11 +24,6 @@ Gem::Specification.new do |spec|
|
|
24
24
|
|
25
25
|
spec.required_ruby_version = '>= 2.3'
|
26
26
|
|
27
|
-
spec.files =
|
28
|
-
`git ls-files -z`.split("\x0").reject do |f|
|
29
|
-
f.match(%r{^(test|spec|features)/})
|
30
|
-
end
|
31
|
-
|
32
27
|
spec.files = Dir['app/**/*', 'config/**/*', 'lib/**/*'] +
|
33
28
|
%w[Rakefile README.md wcc-contentful.gemspec]
|
34
29
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wcc-contentful
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Watermark Dev
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-02-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: byebug
|
@@ -455,6 +455,7 @@ files:
|
|
455
455
|
- lib/wcc/contentful/middleware/store.rb
|
456
456
|
- lib/wcc/contentful/middleware/store/caching_middleware.rb
|
457
457
|
- lib/wcc/contentful/model.rb
|
458
|
+
- lib/wcc/contentful/model_api.rb
|
458
459
|
- lib/wcc/contentful/model_builder.rb
|
459
460
|
- lib/wcc/contentful/model_methods.rb
|
460
461
|
- lib/wcc/contentful/model_singleton_methods.rb
|
@@ -483,6 +484,11 @@ files:
|
|
483
484
|
- lib/wcc/contentful/store/rspec_examples/basic_store.rb
|
484
485
|
- lib/wcc/contentful/store/rspec_examples/include_param.rb
|
485
486
|
- lib/wcc/contentful/store/rspec_examples/nested_queries.rb
|
487
|
+
- lib/wcc/contentful/store/rspec_examples/operators.rb
|
488
|
+
- lib/wcc/contentful/store/rspec_examples/operators/eq.rb
|
489
|
+
- lib/wcc/contentful/store/rspec_examples/operators/in.rb
|
490
|
+
- lib/wcc/contentful/store/rspec_examples/operators/ne.rb
|
491
|
+
- lib/wcc/contentful/store/rspec_examples/operators/nin.rb
|
486
492
|
- lib/wcc/contentful/sync_engine.rb
|
487
493
|
- lib/wcc/contentful/sys.rb
|
488
494
|
- lib/wcc/contentful/test.rb
|
@@ -495,8 +501,8 @@ homepage: https://github.com/watermarkchurch/wcc-contentful/wcc-contentful
|
|
495
501
|
licenses:
|
496
502
|
- MIT
|
497
503
|
metadata:
|
498
|
-
documentation_uri: https://watermarkchurch.github.io/wcc-contentful/1.
|
499
|
-
post_install_message:
|
504
|
+
documentation_uri: https://watermarkchurch.github.io/wcc-contentful/1.1/wcc-contentful
|
505
|
+
post_install_message:
|
500
506
|
rdoc_options: []
|
501
507
|
require_paths:
|
502
508
|
- lib
|
@@ -511,9 +517,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
511
517
|
- !ruby/object:Gem::Version
|
512
518
|
version: '0'
|
513
519
|
requirements: []
|
514
|
-
rubyforge_project:
|
520
|
+
rubyforge_project:
|
515
521
|
rubygems_version: 2.7.6.2
|
516
|
-
signing_key:
|
522
|
+
signing_key:
|
517
523
|
specification_version: 4
|
518
524
|
summary: '[](https://rubygems.org/gems/wcc-contentful)
|
519
525
|
[](https://circleci.com/gh/watermarkchurch/wcc-contentful)
|
@@ -525,17 +531,18 @@ summary: '[](https://
|
|
525
531
|
2. [Installation](#installation) 3. [Configuration](#configure) 4. [Usage](#usage)
|
526
532
|
1. [Model API](#wcccontentfulmodel-api) 2. [Store API](#store-api) 3. [Direct CDN
|
527
533
|
client](#direct-cdn-api-simpleclient) 4. [Accessing the APIs](#accessing-the-apis-within-application-code)
|
528
|
-
5. [Architecture](#architecture)
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
534
|
+
5. [Architecture](#architecture) 1. [Client Layer](#client-layer) 2. [Store Layer](#store-layer)
|
535
|
+
3. [Model Layer](#model-layer) 6. [Test Helpers](#test-helpers) 7. [Advanced Configuration
|
536
|
+
Example](#advanced-configuration-example) 8. [Connecting to Multiple Spaces](#connecting-to-multiple-spaces-or-environments)
|
537
|
+
9. [Development](#development) 10. [Contributing](#contributing) 11. [License](#license) ##
|
538
|
+
Why did you rewrite the Contentful ruby stack? We started working with Contentful
|
539
|
+
almost 3 years ago. Since that time, Contentful''s ruby stack has improved, but
|
540
|
+
there are still a number of pain points that we feel we have addressed better with
|
541
|
+
our gem. These are: * [Low-level caching](#low-level-caching) * [Better integration
|
542
|
+
with Rails & Rails models](#better-rails-integration) * [Automatic pagination and
|
543
|
+
Automatic link resolution](#automatic-pagination-and-link-resolution) * [Automatic
|
544
|
+
webhook management](#automatic-webhook-management) Our gem no longer depends on
|
545
|
+
any of the Contentful gems and interacts directly with the [Contentful CDA](https://www.contentful.com/developers/docs/references/content-delivery-api/)
|
539
546
|
and [Content Management API](https://www.contentful.com/developers/docs/references/content-management-api/)
|
540
547
|
over HTTPS. ### Low-level caching The wcc-contentful gem enables caching at two
|
541
548
|
levels: the HTTP response using [Faraday HTTP cache middleware](https://github.com/sourcelevel/faraday-http-cache),
|
@@ -552,7 +559,7 @@ summary: '[](https://
|
|
552
559
|
for one implementation). Using Faraday makes it easy to add Middleware. As an
|
553
560
|
example, our flagship Rails app that powers watermark.org uses the following configuration
|
554
561
|
in Production, which provides us with instrumentation through statsd, logging, and
|
555
|
-
caching: ```
|
562
|
+
caching: ```ruby config.connection = Faraday.new do |builder| builder.use :http_cache,
|
556
563
|
shared_cache: false, store: ActiveSupport::Cache::MemoryStore.new(size: 512.megabytes),
|
557
564
|
logger: Rails.logger, serializer: Marshal, instrumenter: ActiveSupport::Notifications builder.use
|
558
565
|
:gzip builder.response :logger, Rails.logger, headers: false, bodies: false if Rails.env.development?
|
@@ -584,7 +591,7 @@ summary: '[](https://
|
|
584
591
|
content model registry allows easy definition of custom models in your `app/models`
|
585
592
|
directory to override fields. This plays nice with other gems like algoliasearch-rails,
|
586
593
|
which allows you to declaratively manage your Algolia indexes. Another example
|
587
|
-
from our flagship watermark.org: ```
|
594
|
+
from our flagship watermark.org: ```ruby class Page < WCC::Contentful::Model::Page
|
588
595
|
include AlgoliaSearch algoliasearch(index_name: ''pages'') do attribute(:title,
|
589
596
|
:slug) ... end ``` ### Automatic Pagination and Link Resolution Using the `contentful_model`
|
590
597
|
gem, calling `Page.all.load` does not give you all Page entries if there are more
|
@@ -678,12 +685,55 @@ summary: '[](https://
|
|
678
685
|
gives access to the other configured services. You can also include the {WCC::Contentful::ServiceAccessors}
|
679
686
|
concern to define these services as attributes in a class. ```ruby class MyJob
|
680
687
|
< ApplicationJob include WCC::Contentful::ServiceAccessors def perform Page.find(...) store.find(...) client.entries(...)
|
681
|
-
end end ``` ## Architecture 
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
688
|
+
end end ``` ## Architecture  From
|
689
|
+
the bottom up: ### Client Layer The {WCC::Contentful::SimpleClient} provides methods
|
690
|
+
to access the [Contentful Content Delivery API](https://www.contentful.com/developers/docs/references/content-delivery-api/)
|
691
|
+
through your favorite HTTP client gem. The SimpleClient expects an Adapter that
|
692
|
+
conforms to the Faraday interface. Creating a SimpleClient to connect using different
|
693
|
+
credentials, or to connect without setting up all the rest of WCC::Contentful, is
|
694
|
+
easy: ```ruby WCC::Contentful::SimpleClient::Cdn.new( # required access_token:
|
695
|
+
''xxxx'', space: ''1234'', # optional environment: ''staging'', # omit to use master
|
696
|
+
default_locale: ''*'', rate_limit_wait_timeout: 10, instrumentation: ActiveSupport::Notifications,
|
697
|
+
connection: Faraday.new { |builder| ... }, ) ``` You can also create a {WCC::Contentful::SimpleClient::Preview}
|
698
|
+
to talk to the Preview API, or a {WCC::Contentful::SimpleClient::Management} to
|
699
|
+
talk to the Management API. ### Store Layer The Store Layer represents the data
|
700
|
+
store where Contentful entries are kept for querying. By default, `WCC::Contentful.init!`
|
701
|
+
creates a {WCC::Contentful::Store::CDNAdapter} which uses a {WCC::Contentful::SimpleClient::Cdn}
|
702
|
+
instance to query entries from the [Contentful Content Delivery API](https://www.contentful.com/developers/docs/references/content-delivery-api/). You
|
703
|
+
can also query entries from another source like Postgres or an in-memory hash if
|
704
|
+
your data is small enough. You can also implement your own store if you want! The
|
705
|
+
gem contains a suite of RSpec shared examples that give you a baseline for implementing
|
706
|
+
your own store. In your RSpec suite: ```ruby # frozen_string_literal: true require
|
707
|
+
''my_store'' require ''wcc/contentful/store/rspec_examples'' RSpec.describe MyStore
|
708
|
+
do it_behaves_like ''contentful store'', { # Set which store features your store
|
709
|
+
implements. nested_queries: true, # Does your store implement JOINs? include_param:
|
710
|
+
true # Does your store resolve links when given the :include option? } ``` The
|
711
|
+
store is kept up-to-date by the {WCC::Contentful::SyncEngine}. The `SyncEngine#next`
|
712
|
+
methodcalls the `#index` method on the configured store in order to update it with
|
713
|
+
the latest data via the [Contentful Sync API](https://www.contentful.com/developers/docs/references/content-delivery-api/#/reference/synchronization). For
|
714
|
+
example, the {WCC::Contentful::Store::MemoryStore} uses this to update the hash
|
715
|
+
with the newest version of an entry, or delete an entry out of the hash. #### Store
|
716
|
+
Middleware The store layer is made up of a base store (which implements {WCC::Contentful::Store::Interface}),
|
717
|
+
and optional middleware. The middleware allows custom transformation of received
|
718
|
+
entries via the `#select` and `#transform` methods. To create your own middleware
|
719
|
+
simply include {WCC::Contentful::Middleware::Store} and implement those methods,
|
720
|
+
then call `use` when configuring the store: ```ruby config.store :direct do use
|
721
|
+
MyMiddleware, param1: ''xxx'' end ``` The most useful middleware is the {WCC::Contentful::Middleware::Store::CachingMiddleware},
|
722
|
+
which enables `:lazy_sync` mode (see {WCC::Contentful::Configuration#store}) ###
|
723
|
+
Model Layer This is the global top layer where your Rails app looks up content
|
724
|
+
similarly to ActiveModel. The models are namespaced under the root class {WCC::Contentful::Model}.
|
725
|
+
Each model''s implementation of `.find`, `.find_by`, and `.find_all` simply call
|
726
|
+
into the configured Store. The main benefit of the Model layer is lazy link resolution. When
|
727
|
+
a model''s property is accessed, if that property is a link that has not been resolved
|
728
|
+
yet (for example using the `include: n` parameter on `.find_by`), the model will
|
729
|
+
automatically call `#find` on the store to resolve that linked entry. Note that
|
730
|
+
this can easily result in lots of CDN calls to Contentful! To optimize this you
|
731
|
+
should use the `include` parameter and/or use a different store. ## Test Helpers To
|
732
|
+
use the test helpers, include the following in your rails_helper.rb: ```ruby require
|
733
|
+
''wcc/contentful/rspec'' ``` This adds the following helpers to all your specs: ```ruby
|
734
|
+
## # Builds a in-memory instance of the Contentful model for the given content_type.
|
735
|
+
# All attributes that are known to be required fields on the content type # will
|
736
|
+
return a default value based on the field type. instance = contentful_create(''my-content-type'',
|
687
737
|
my_field: ''some-value'') # => #<WCC::Contentful::Model::MyContentType:0x0000000005c71a78
|
688
738
|
@created_at=2018-04-16 18:41:17 UTC...> instance.my_field # => "some-value" instance.other_required_field
|
689
739
|
# => "default-value" instance.other_optional_field # => nil instance.not_a_field
|
@@ -720,16 +770,46 @@ summary: '[](https://
|
|
720
770
|
\ -s $CONTENTFUL_SPACE_ID -a $CONTENTFUL_MANAGEMENT_TOKEN \ -y -p "$migrations_to_be_run" echo
|
721
771
|
"Updating schema file..." rake wcc_contentful:download_schema ``` All configuration
|
722
772
|
options can be found [in the rubydoc](https://www.rubydoc.info/gems/wcc-contentful/WCC/Contentful/Configuration)
|
723
|
-
under {WCC::Contentful::Configuration}
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
773
|
+
under {WCC::Contentful::Configuration} ## Connecting to multiple spaces or environments When
|
774
|
+
initializing the WCC::Contentful gem using `WCC::Contentful.init!`, the gem will
|
775
|
+
by default connect to the single Contentful space that you specify in the `WCC::Contentful.configure`
|
776
|
+
step. However the gem is also capable of connecting to multiple spaces within the
|
777
|
+
same ruby process! You just have to create and initialize a namespace. The {WCC::Contentful::ModelAPI}
|
778
|
+
concern makes this straightforward. Start by creating your Namespace and including
|
779
|
+
the concern: ```ruby # app/models/my_second_space.rb class MySecondSpace include
|
780
|
+
WCC::Contentful::ModelAPI end # app/models/other_page.rb class OtherPage < MySecondSpace::Page
|
781
|
+
end ``` Then configure it in an initializer: ```ruby # config/initializers/my_second_space.rb
|
782
|
+
MySecondSpace.configure do |config| # Make sure to point to a different schema file
|
783
|
+
from your first space! config.schema_file = Rails.root.join(''db/second-contentful-schema.json'') config.access_token
|
784
|
+
= ENV[''SECOND_CONTENTFUL_ACCESS_TOKEN''] config.preview_token = ENV[''SECOND_CONTENTFUL_PREVIEW_ACCESS_TOKEN'']
|
785
|
+
config.space = ENV[''SECOND_CONTENTFUL_SPACE_ID''] config.environment = ENV[''CONTENTFUL_ENVIRONMENT'']
|
786
|
+
end ``` Finally, use it: ```ruby OtherPage.find(''1234'') # GET https://cdn.contentful.com/spaces/other-space/environments/other-env/entries/1234
|
787
|
+
# => #<OtherPage:0x0000000005c71a78 @created_at=2018-04-16 18:41:17 UTC...> Page.find(''1234'')
|
788
|
+
# GET https://cdn.contentful.com/spaces/first-space/environments/first-env/entries/1234
|
789
|
+
# => #<Page:0x0000000001271b70 @created_at=2018-04-15 12:02:14 UTC...> ``` The
|
790
|
+
ModelAPI defines a second stack of services that you can access for lower level
|
791
|
+
connections: ```ruby store = MySecondSpace.services.store # => #<WCC::Contentful::Store::CDNAdapter:0x00007f888edac118
|
792
|
+
client = MySecondSpace.services.client # => #<WCC::Contentful::SimpleClient::Cdn:0x00007f88942a8888
|
793
|
+
preview_client = MySecondSpace.services.preview_client # => #<WCC::Contentful::SimpleClient::Preview:0x00007f888ccafa00
|
794
|
+
sync_engine = MySecondSpace.services.sync_engine # => #<WCC::Contentful::SyncEngine:0x00007f88960b6b40
|
795
|
+
``` Note that the above services are not accessible on {WCC::Contentful::Services.instance}
|
796
|
+
or via the {WCC::Contentful::ServiceAccessors}. ### Using a sync store with a second
|
797
|
+
space If you use something other than the CDNAdapter with your second space, you
|
798
|
+
will need to find a way to trigger `MySecondSpace.services.sync_engine.next` to
|
799
|
+
keep it up-to-date. The {WCC::Contentful::Engine} will only manage the global SyncEngine
|
800
|
+
configured by the global {WCC::Contentful.configure}. The easiest way to do this
|
801
|
+
is to set up your own Rails route to respond to Contentful webhooks and then configure
|
802
|
+
the second Contentful space to send webhooks to this route. You could also do this
|
803
|
+
by triggering it periodically in a background job using Sidekiq and [sidekiq-scheduler](https://github.com/Moove-it/sidekiq-scheduler). ##
|
804
|
+
Development After checking out the repo, run `bin/setup` to install dependencies.
|
805
|
+
Then, run `bundle exec rspec` to run the tests. You can also run `bin/console` for
|
806
|
+
an interactive prompt that will allow you to experiment. ## Contributing Bug reports
|
807
|
+
and pull requests are welcome on GitHub at https://github.com/watermarkchurch/wcc-contentful. The
|
808
|
+
developers at Watermark Community Church have pledged to govern their interactions
|
809
|
+
with each other, with their clients, and with the larger wcc-contentful user community
|
810
|
+
in accordance with the "instruments of good works" from chapter 4 of The Rule of
|
811
|
+
St. Benedict (hereafter: "The Rule"). This code of ethics has proven its mettle
|
812
|
+
in thousands of diverse communities for over 1,500 years, and has served as a baseline
|
813
|
+
for many civil law codes since the time of Charlemagne. [See the full Code of Ethics](https://github.com/watermarkchurch/wcc-contentful/blob/master/CODE_OF_ETHICS.md) ##
|
734
814
|
License The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).'
|
735
815
|
test_files: []
|