wcc-contentful 1.0.8 → 1.1.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.
@@ -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
- attr_reader :types
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
- @content_types =
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 !@content_types && %i[if_possible never].include?(configuration.update_schema_file)
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
- @content_types = client.content_types(limit: 1000).items if client
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 @content_types
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
- indexer = ContentTypeIndexer.from_json_schema(@content_types)
124
- @types = indexer.types
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
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.0.8
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Watermark Dev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-14 00:00:00.000000000 Z
11
+ date: 2022-02-02 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
@@ -495,7 +496,7 @@ homepage: https://github.com/watermarkchurch/wcc-contentful/wcc-contentful
495
496
  licenses:
496
497
  - MIT
497
498
  metadata:
498
- documentation_uri: https://watermarkchurch.github.io/wcc-contentful/1.0/wcc-contentful
499
+ documentation_uri: https://watermarkchurch.github.io/wcc-contentful/1.1/wcc-contentful
499
500
  post_install_message:
500
501
  rdoc_options: []
501
502
  require_paths:
@@ -525,17 +526,18 @@ summary: '[![Gem Version](https://badge.fury.io/rb/wcc-contentful.svg)](https://
525
526
  2. [Installation](#installation) 3. [Configuration](#configure) 4. [Usage](#usage)
526
527
  1. [Model API](#wcccontentfulmodel-api) 2. [Store API](#store-api) 3. [Direct CDN
527
528
  client](#direct-cdn-api-simpleclient) 4. [Accessing the APIs](#accessing-the-apis-within-application-code)
528
- 5. [Architecture](#architecture) 6. [Test Helpers](#test-helpers) 7. [Advanced Configuration
529
- Example](#advanced-configuration-example) 8. [Development](#development) 9. [Contributing](#contributing)
530
- 10. [License](#license) ## Why did you rewrite the Contentful ruby stack? We
531
- started working with Contentful almost 3 years ago. Since that time, Contentful''s
532
- ruby stack has improved, but there are still a number of pain points that we feel
533
- we have addressed better with our gem. These are: * [Low-level caching](#low-level-caching)
534
- * [Better integration with Rails & Rails models](#better-rails-integration) * [Automatic
535
- pagination and Automatic link resolution](#automatic-pagination-and-link-resolution)
536
- * [Automatic webhook management](#automatic-webhook-management) Our gem no longer
537
- depends on any of the Contentful gems and interacts directly with the [Contentful
538
- CDA](https://www.contentful.com/developers/docs/references/content-delivery-api/)
529
+ 5. [Architecture](#architecture) 1. [Client Layer](#client-layer) 2. [Store Layer](#store-layer)
530
+ 3. [Model Layer](#model-layer) 6. [Test Helpers](#test-helpers) 7. [Advanced Configuration
531
+ Example](#advanced-configuration-example) 8. [Connecting to Multiple Spaces](#connecting-to-multiple-spaces-or-environments)
532
+ 9. [Development](#development) 10. [Contributing](#contributing) 11. [License](#license) ##
533
+ Why did you rewrite the Contentful ruby stack? We started working with Contentful
534
+ almost 3 years ago. Since that time, Contentful''s ruby stack has improved, but
535
+ there are still a number of pain points that we feel we have addressed better with
536
+ our gem. These are: * [Low-level caching](#low-level-caching) * [Better integration
537
+ with Rails & Rails models](#better-rails-integration) * [Automatic pagination and
538
+ Automatic link resolution](#automatic-pagination-and-link-resolution) * [Automatic
539
+ webhook management](#automatic-webhook-management) Our gem no longer depends on
540
+ any of the Contentful gems and interacts directly with the [Contentful CDA](https://www.contentful.com/developers/docs/references/content-delivery-api/)
539
541
  and [Content Management API](https://www.contentful.com/developers/docs/references/content-management-api/)
540
542
  over HTTPS. ### Low-level caching The wcc-contentful gem enables caching at two
541
543
  levels: the HTTP response using [Faraday HTTP cache middleware](https://github.com/sourcelevel/faraday-http-cache),
@@ -552,7 +554,7 @@ summary: '[![Gem Version](https://badge.fury.io/rb/wcc-contentful.svg)](https://
552
554
  for one implementation). Using Faraday makes it easy to add Middleware. As an
553
555
  example, our flagship Rails app that powers watermark.org uses the following configuration
554
556
  in Production, which provides us with instrumentation through statsd, logging, and
555
- caching: ```rb config.connection = Faraday.new do |builder| builder.use :http_cache,
557
+ caching: ```ruby config.connection = Faraday.new do |builder| builder.use :http_cache,
556
558
  shared_cache: false, store: ActiveSupport::Cache::MemoryStore.new(size: 512.megabytes),
557
559
  logger: Rails.logger, serializer: Marshal, instrumenter: ActiveSupport::Notifications builder.use
558
560
  :gzip builder.response :logger, Rails.logger, headers: false, bodies: false if Rails.env.development?
@@ -584,7 +586,7 @@ summary: '[![Gem Version](https://badge.fury.io/rb/wcc-contentful.svg)](https://
584
586
  content model registry allows easy definition of custom models in your `app/models`
585
587
  directory to override fields. This plays nice with other gems like algoliasearch-rails,
586
588
  which allows you to declaratively manage your Algolia indexes. Another example
587
- from our flagship watermark.org: ```rb class Page < WCC::Contentful::Model::Page
589
+ from our flagship watermark.org: ```ruby class Page < WCC::Contentful::Model::Page
588
590
  include AlgoliaSearch algoliasearch(index_name: ''pages'') do attribute(:title,
589
591
  :slug) ... end ``` ### Automatic Pagination and Link Resolution Using the `contentful_model`
590
592
  gem, calling `Page.all.load` does not give you all Page entries if there are more
@@ -678,12 +680,55 @@ summary: '[![Gem Version](https://badge.fury.io/rb/wcc-contentful.svg)](https://
678
680
  gives access to the other configured services. You can also include the {WCC::Contentful::ServiceAccessors}
679
681
  concern to define these services as attributes in a class. ```ruby class MyJob
680
682
  < ApplicationJob include WCC::Contentful::ServiceAccessors def perform Page.find(...) store.find(...) client.entries(...)
681
- end end ``` ## Architecture ![wcc-contentful diagram](./doc-static/wcc-contentful.png) ##
682
- Test Helpers To use the test helpers, include the following in your rails_helper.rb: ```ruby
683
- require ''wcc/contentful/rspec'' ``` This adds the following helpers to all your
684
- specs: ```ruby ## # Builds a in-memory instance of the Contentful model for the
685
- given content_type. # All attributes that are known to be required fields on the
686
- content type # will return a default value based on the field type. instance = contentful_create(''my-content-type'',
683
+ end end ``` ## Architecture ![wcc-contentful diagram](./doc-static/wcc-contentful.png) From
684
+ the bottom up: ### Client Layer The {WCC::Contentful::SimpleClient} provides methods
685
+ to access the [Contentful Content Delivery API](https://www.contentful.com/developers/docs/references/content-delivery-api/)
686
+ through your favorite HTTP client gem. The SimpleClient expects an Adapter that
687
+ conforms to the Faraday interface. Creating a SimpleClient to connect using different
688
+ credentials, or to connect without setting up all the rest of WCC::Contentful, is
689
+ easy: ```ruby WCC::Contentful::SimpleClient::Cdn.new( # required access_token:
690
+ ''xxxx'', space: ''1234'', # optional environment: ''staging'', # omit to use master
691
+ default_locale: ''*'', rate_limit_wait_timeout: 10, instrumentation: ActiveSupport::Notifications,
692
+ connection: Faraday.new { |builder| ... }, ) ``` You can also create a {WCC::Contentful::SimpleClient::Preview}
693
+ to talk to the Preview API, or a {WCC::Contentful::SimpleClient::Management} to
694
+ talk to the Management API. ### Store Layer The Store Layer represents the data
695
+ store where Contentful entries are kept for querying. By default, `WCC::Contentful.init!`
696
+ creates a {WCC::Contentful::Store::CDNAdapter} which uses a {WCC::Contentful::SimpleClient::Cdn}
697
+ instance to query entries from the [Contentful Content Delivery API](https://www.contentful.com/developers/docs/references/content-delivery-api/). You
698
+ can also query entries from another source like Postgres or an in-memory hash if
699
+ your data is small enough. You can also implement your own store if you want! The
700
+ gem contains a suite of RSpec shared examples that give you a baseline for implementing
701
+ your own store. In your RSpec suite: ```ruby # frozen_string_literal: true require
702
+ ''my_store'' require ''wcc/contentful/store/rspec_examples'' RSpec.describe MyStore
703
+ do it_behaves_like ''contentful store'', { # Set which store features your store
704
+ implements. nested_queries: true, # Does your store implement JOINs? include_param:
705
+ true # Does your store resolve links when given the :include option? } ``` The
706
+ store is kept up-to-date by the {WCC::Contentful::SyncEngine}. The `SyncEngine#next`
707
+ methodcalls the `#index` method on the configured store in order to update it with
708
+ the latest data via the [Contentful Sync API](https://www.contentful.com/developers/docs/references/content-delivery-api/#/reference/synchronization). For
709
+ example, the {WCC::Contentful::Store::MemoryStore} uses this to update the hash
710
+ with the newest version of an entry, or delete an entry out of the hash. #### Store
711
+ Middleware The store layer is made up of a base store (which implements {WCC::Contentful::Store::Interface}),
712
+ and optional middleware. The middleware allows custom transformation of received
713
+ entries via the `#select` and `#transform` methods. To create your own middleware
714
+ simply include {WCC::Contentful::Middleware::Store} and implement those methods,
715
+ then call `use` when configuring the store: ```ruby config.store :direct do use
716
+ MyMiddleware, param1: ''xxx'' end ``` The most useful middleware is the {WCC::Contentful::Middleware::Store::CachingMiddleware},
717
+ which enables `:lazy_sync` mode (see {WCC::Contentful::Configuration#store}) ###
718
+ Model Layer This is the global top layer where your Rails app looks up content
719
+ similarly to ActiveModel. The models are namespaced under the root class {WCC::Contentful::Model}.
720
+ Each model''s implementation of `.find`, `.find_by`, and `.find_all` simply call
721
+ into the configured Store. The main benefit of the Model layer is lazy link resolution. When
722
+ a model''s property is accessed, if that property is a link that has not been resolved
723
+ yet (for example using the `include: n` parameter on `.find_by`), the model will
724
+ automatically call `#find` on the store to resolve that linked entry. Note that
725
+ this can easily result in lots of CDN calls to Contentful! To optimize this you
726
+ should use the `include` parameter and/or use a different store. ## Test Helpers To
727
+ use the test helpers, include the following in your rails_helper.rb: ```ruby require
728
+ ''wcc/contentful/rspec'' ``` This adds the following helpers to all your specs: ```ruby
729
+ ## # Builds a in-memory instance of the Contentful model for the given content_type.
730
+ # All attributes that are known to be required fields on the content type # will
731
+ return a default value based on the field type. instance = contentful_create(''my-content-type'',
687
732
  my_field: ''some-value'') # => #<WCC::Contentful::Model::MyContentType:0x0000000005c71a78
688
733
  @created_at=2018-04-16 18:41:17 UTC...> instance.my_field # => "some-value" instance.other_required_field
689
734
  # => "default-value" instance.other_optional_field # => nil instance.not_a_field
@@ -720,16 +765,46 @@ summary: '[![Gem Version](https://badge.fury.io/rb/wcc-contentful.svg)](https://
720
765
  \ -s $CONTENTFUL_SPACE_ID -a $CONTENTFUL_MANAGEMENT_TOKEN \ -y -p "$migrations_to_be_run" echo
721
766
  "Updating schema file..." rake wcc_contentful:download_schema ``` All configuration
722
767
  options can be found [in the rubydoc](https://www.rubydoc.info/gems/wcc-contentful/WCC/Contentful/Configuration)
723
- under {WCC::Contentful::Configuration} ## Development After checking out the
724
- repo, run `bin/setup` to install dependencies. Then, run `bundle exec rspec` to
725
- run the tests. You can also run `bin/console` for an interactive prompt that will
726
- allow you to experiment. ## Contributing Bug reports and pull requests are welcome
727
- on GitHub at https://github.com/watermarkchurch/wcc-contentful. The developers
728
- at Watermark Community Church have pledged to govern their interactions with each
729
- other, with their clients, and with the larger wcc-contentful user community in
730
- accordance with the "instruments of good works" from chapter 4 of The Rule of St.
731
- Benedict (hereafter: "The Rule"). This code of ethics has proven its mettle in thousands
732
- of diverse communities for over 1,500 years, and has served as a baseline for many
733
- 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) ##
768
+ under {WCC::Contentful::Configuration} ## Connecting to multiple spaces or environments When
769
+ initializing the WCC::Contentful gem using `WCC::Contentful.init!`, the gem will
770
+ by default connect to the single Contentful space that you specify in the `WCC::Contentful.configure`
771
+ step. However the gem is also capable of connecting to multiple spaces within the
772
+ same ruby process! You just have to create and initialize a namespace. The {WCC::Contentful::ModelAPI}
773
+ concern makes this straightforward. Start by creating your Namespace and including
774
+ the concern: ```ruby # app/models/my_second_space.rb class MySecondSpace include
775
+ WCC::Contentful::ModelAPI end # app/models/other_page.rb class OtherPage < MySecondSpace::Page
776
+ end ``` Then configure it in an initializer: ```ruby # config/initializers/my_second_space.rb
777
+ MySecondSpace.configure do |config| # Make sure to point to a different schema file
778
+ from your first space! config.schema_file = Rails.root.join(''db/second-contentful-schema.json'') config.access_token
779
+ = ENV[''SECOND_CONTENTFUL_ACCESS_TOKEN''] config.preview_token = ENV[''SECOND_CONTENTFUL_PREVIEW_ACCESS_TOKEN'']
780
+ config.space = ENV[''SECOND_CONTENTFUL_SPACE_ID''] config.environment = ENV[''CONTENTFUL_ENVIRONMENT'']
781
+ end ``` Finally, use it: ```ruby OtherPage.find(''1234'') # GET https://cdn.contentful.com/spaces/other-space/environments/other-env/entries/1234
782
+ # => #<OtherPage:0x0000000005c71a78 @created_at=2018-04-16 18:41:17 UTC...> Page.find(''1234'')
783
+ # GET https://cdn.contentful.com/spaces/first-space/environments/first-env/entries/1234
784
+ # => #<Page:0x0000000001271b70 @created_at=2018-04-15 12:02:14 UTC...> ``` The
785
+ ModelAPI defines a second stack of services that you can access for lower level
786
+ connections: ```ruby store = MySecondSpace.services.store # => #<WCC::Contentful::Store::CDNAdapter:0x00007f888edac118
787
+ client = MySecondSpace.services.client # => #<WCC::Contentful::SimpleClient::Cdn:0x00007f88942a8888
788
+ preview_client = MySecondSpace.services.preview_client # => #<WCC::Contentful::SimpleClient::Preview:0x00007f888ccafa00
789
+ sync_engine = MySecondSpace.services.sync_engine # => #<WCC::Contentful::SyncEngine:0x00007f88960b6b40
790
+ ``` Note that the above services are not accessible on {WCC::Contentful::Services.instance}
791
+ or via the {WCC::Contentful::ServiceAccessors}. ### Using a sync store with a second
792
+ space If you use something other than the CDNAdapter with your second space, you
793
+ will need to find a way to trigger `MySecondSpace.services.sync_engine.next` to
794
+ keep it up-to-date. The {WCC::Contentful::Engine} will only manage the global SyncEngine
795
+ configured by the global {WCC::Contentful.configure}. The easiest way to do this
796
+ is to set up your own Rails route to respond to Contentful webhooks and then configure
797
+ the second Contentful space to send webhooks to this route. You could also do this
798
+ by triggering it periodically in a background job using Sidekiq and [sidekiq-scheduler](https://github.com/Moove-it/sidekiq-scheduler). ##
799
+ Development After checking out the repo, run `bin/setup` to install dependencies.
800
+ Then, run `bundle exec rspec` to run the tests. You can also run `bin/console` for
801
+ an interactive prompt that will allow you to experiment. ## Contributing Bug reports
802
+ and pull requests are welcome on GitHub at https://github.com/watermarkchurch/wcc-contentful. The
803
+ developers at Watermark Community Church have pledged to govern their interactions
804
+ with each other, with their clients, and with the larger wcc-contentful user community
805
+ in accordance with the "instruments of good works" from chapter 4 of The Rule of
806
+ St. Benedict (hereafter: "The Rule"). This code of ethics has proven its mettle
807
+ in thousands of diverse communities for over 1,500 years, and has served as a baseline
808
+ 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
809
  License The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).'
735
810
  test_files: []