lib/wcc/contentful.rb in wcc-contentful-0.2.2 vs lib/wcc/contentful.rb in wcc-contentful-0.3.0.pre.rc

- old
+ new

@@ -6,202 +6,74 @@ require 'active_support/core_ext/object' require 'wcc/contentful/configuration' require 'wcc/contentful/exceptions' require 'wcc/contentful/helpers' +require 'wcc/contentful/services' require 'wcc/contentful/simple_client' require 'wcc/contentful/store' require 'wcc/contentful/content_type_indexer' -require 'wcc/contentful/model_validators' require 'wcc/contentful/model' +require 'wcc/contentful/model_methods' +require 'wcc/contentful/model_singleton_methods' require 'wcc/contentful/model_builder' -## # The root namespace of the wcc-contentful gem # # Initialize the gem with the `configure` and `init` methods inside your # initializer. module WCC::Contentful class << self - ## # Gets the current configuration, after calling WCC::Contentful.configure attr_reader :configuration - ## - # Gets the sync token that was returned by the Contentful CDN after the most - # recent invocation of WCC::Contentful.sync! - attr_reader :next_sync_token + attr_reader :types end - ## - # Gets a {CDN Client}[rdoc-ref:WCC::Contentful::SimpleClient::Cdn] which provides - # methods for getting and paging raw JSON data from the Contentful CDN. - def self.client(preview: false) - if preview - configuration&.preview_client - else - configuration&.client - end - end - - ## - # Gets the data-store which executes the queries run against the dynamic - # models in the WCC::Contentful::Model namespace. - # This is one of the following based on the configured content_delivery method: - # - # [:direct] an instance of WCC::Contentful::Store::CDNAdapter with a - # {CDN Client}[rdoc-ref:WCC::Contentful::SimpleClient::Cdn] to access the CDN. - # - # [:lazy_sync] an instance of WCC::Contentful::Store::LazyCacheStore - # with the configured ActiveSupport::Cache implementation and a - # {CDN Client}[rdoc-ref:WCC::Contentful::SimpleClient::Cdn] for when data - # cannot be found in the cache. - # - # [:eager_sync] an instance of the configured Store type, defined by - # WCC::Contentful::Configuration.sync_store - # - def self.store - WCC::Contentful::Model.store - end - - def self.preview_store - WCC::Contentful::Model.preview_store - end - - ## # Configures the WCC::Contentful gem to talk to a Contentful space. # This must be called first in your initializer, before #init! or accessing the # client. def self.configure @configuration ||= Configuration.new - @next_sync_token = nil yield(configuration) configuration.validate! - configuration.configure_contentful - configuration end - ## # Initializes the WCC::Contentful model-space and backing store. # This populates the WCC::Contentful::Model namespace with Ruby classes # that represent content types in the configured Contentful space. # # These content types can be queried directly: # WCC::Contentful::Model::Page.find('1xab...') # Or you can inherit from them in your own app: - # class Page < WCC::Contentful::Model.page; end + # class Page < WCC::Contentful::Model::Page; end # Page.find_by(slug: 'about-us') def self.init! raise ArgumentError, 'Please first call WCC:Contentful.configure' if configuration.nil? - @mutex ||= Mutex.new - use_preview_client = false - # we want as much as possible the raw JSON from the API - content_types_resp = - if configuration.management_client - configuration.management_client.content_types(limit: 1000) - else - configuration.client.content_types(limit: 1000) - end + # we want as much as possible the raw JSON from the API so use the management + # client if possible + client = Services.instance.management_client || + Services.instance.client - (use_preview_client = true) unless configuration.preview_client.nil? + @content_types = client.content_types(limit: 1000).items - @content_types = content_types_resp.items - indexer = ContentTypeIndexer.new.tap do |ixr| @content_types.each { |type| ixr.index(type) } end @types = indexer.types - if use_preview_client - store = configuration.store(preview: false) - WCC::Contentful::Model.store = store - preview_store = configuration.store(preview: use_preview_client) - WCC::Contentful::Model.preview_store = preview_store - else - store = configuration.store(preview: use_preview_client) - WCC::Contentful::Model.store = store - end - + store = Services.instance.store if store.respond_to?(:index) - @next_sync_token = store.find("sync:#{configuration.space}:token") - sync! + # Drop an initial sync + WCC::Contentful::DelayedSyncJob.perform_later end WCC::Contentful::ModelBuilder.new(@types).build_models - # Extend all model types w/ validation & extra fields - @types.each_value do |t| - file = File.dirname(__FILE__) + "/contentful/model/#{t.name.underscore}.rb" - require file if File.exist?(file) - end + require_relative 'contentful/client_ext' if defined?(::Contentful) end - - ## - # Runs validations over the content types returned from the Contentful API. - # Validations are configured on predefined model classes using the - # `validate_field` directive. Example: - # validate_field :top_button, :Link, :optional, link_to: 'menuButton' - # This results in a WCC::Contentful::ValidationError - # if the 'topButton' field in the 'menu' content type is not a link. - def self.validate_models! - # Ensure application models are loaded before we validate - Dir[Rails.root.join('app/models/**/*.rb')].each { |file| require file } if defined?(Rails) - - content_types = WCC::Contentful::ModelValidators.transform_content_types_for_validation( - @content_types - ) - errors = WCC::Contentful::Model.schema.call(content_types) - raise WCC::Contentful::ValidationError, errors.errors unless errors.success? - end - - ## - # Calls the Contentful Sync API and updates the configured store with the returned - # data. - # - # up_to_id: An ID that we know has changed and should come back from the sync. - # If we don't find this ID in the sync data, then drop a job to try - # the sync again after a few minutes. - # - def self.sync!(up_to_id: nil) - return unless store.respond_to?(:index) - - @mutex.synchronize do - sync_resp = client.sync(sync_token: next_sync_token) - - id_found = up_to_id.nil? - - sync_resp.items.each do |item| - id = item.dig('sys', 'id') - id_found ||= id == up_to_id - store.index(item) - end - store.set("sync:#{configuration.space}:token", sync_resp.next_sync_token) - @next_sync_token = sync_resp.next_sync_token - - unless id_found - raise SyncError, "ID '#{up_to_id}' did not come back via sync." unless defined?(Rails) - sync_later!(up_to_id: up_to_id) - end - next_sync_token - end - end - - ## - # Drops an ActiveJob job to invoke WCC::Contentful.sync! after a given amount - # of time. - def self.sync_later!(up_to_id: nil, wait: 10.minutes) - raise NotImplementedError, 'Cannot sync_later! outside of a Rails app' unless defined?(Rails) - - WCC::Contentful::DelayedSyncJob.set(wait: wait).perform_later(up_to_id) - end - - # TODO: https://zube.io/watermarkchurch/development/c/2234 init graphql - # def self.init_graphql! - # require 'wcc/contentful/graphql' - # etc... - # end end