contentful_rails 0.0.9 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9952955574499fc5fd15c613dc0650c2d68d6be4
4
- data.tar.gz: f7c079e0b606ee381d58b56a83a9a50f6e5c25e4
3
+ metadata.gz: 020e69292f25bc884fa90c49bd9a1a8d7182e249
4
+ data.tar.gz: 45d6590bc12f515276302ac8400b3d3b4c4b80fc
5
5
  SHA512:
6
- metadata.gz: 48f9f9df90f08dcb70d7a507bb9238a3beadfaf5511acd332d0ff573ec80fa2458bf8727ba5fd8e2a031b3602585a810fd78e79830784f0713ddc71948d4ee5f
7
- data.tar.gz: 32aa569a4ffc4c0381ccb4328d1c8c2e80e509b63bc81d42a53bdbb8f2e32c5e292431020e51a11abe3aa85a3f3a0578fb1aa0f9adb695eaad1bafa9706e5121
6
+ metadata.gz: 2aedf217e1096fcda85385e891706a39be4606bb5696ba3683af33aad0fb414b0f859316ad648fcc01d3dca246e1dac4efdf6847dfd2bc9c1daa644fc31e9955
7
+ data.tar.gz: dd9de11844ecb8075a8f3a995d272e9ab6678ba9cb1853f44556cb3a7a8ad24716dfc004131935a410efbbfefda945561109a93b18932d286c4f93d905d0f706
@@ -16,14 +16,11 @@ class ContentfulRails::WebhooksController < ActionController::Base
16
16
  # We can then just use normal Rails russian doll caching without expensive API calls.
17
17
  request.format = :json
18
18
  update_type = request.headers['HTTP_X_CONTENTFUL_TOPIC']
19
- content_type_id = params[:sys][:contentType][:sys][:id]
20
- item_id = params[:sys][:id]
21
- cache_key = "contentful_timestamp/#{content_type_id}/#{item_id}"
22
-
23
- #delete the cache entry
24
- if update_type =~ %r(Entry)
25
- Rails.cache.delete(cache_key)
26
- end
19
+
20
+ # All we do here is publish an ActiveSupport::Notification, which is subscribed to
21
+ # elsewhere. In this gem are subscription options for timestamp or object caching,
22
+ # implement your own and subscribe in an initializer.
23
+ ActiveSupport::Notifications.instrument("Contentful.#{update_type}", params)
27
24
 
28
25
  #must return an ok
29
26
  render nothing: true
@@ -6,6 +6,7 @@ module ContentfulRails
6
6
  # @param renderer_options [Hash] of options from https://github.com/vmg/redcarpet#darling-i-packed-you-a-couple-renderers-for-lunch
7
7
  # @param markdown_options [Hash] of options from https://github.com/vmg/redcarpet#and-its-like-really-simple-to-use
8
8
  def parse_markdown(markdown_string, renderer_options: {}, markdown_options: {}, image_options: {})
9
+ markdown_string ||= ""
9
10
  markdown_opts = {
10
11
  no_intr_emphasis: true,
11
12
  tables: true,
@@ -1,9 +1,10 @@
1
1
  require "contentful_rails/engine"
2
2
  require "contentful_rails/development_constraint"
3
- require "contentful_rails/cached_timestamps"
3
+ require 'contentful_rails/caching/timestamps'
4
4
  require "contentful_rails/markdown_renderer"
5
5
  require "contentful_rails/nested_resource"
6
6
  require "contentful_rails/sluggable"
7
+ require "contentful_rails/preview"
7
8
  require 'redcarpet'
8
9
 
9
10
  module ContentfulRails
@@ -17,10 +18,25 @@ module ContentfulRails
17
18
  end
18
19
 
19
20
  class Configuration
20
- attr_accessor :authenticate_webhooks, :webhooks_username, :webhooks_password
21
+ attr_accessor :authenticate_webhooks,
22
+ :webhooks_username,
23
+ :webhooks_password,
24
+ :slug_delimiter,
25
+ :perform_caching,
26
+ :access_token,
27
+ :preview_access_token,
28
+ :space,
29
+ :contentful_options,
30
+ :preview_username,
31
+ :preview_password,
32
+ :preview_domain,
33
+ :enable_preview_domain
21
34
 
22
35
  def initialize
23
36
  @authenticate = true
37
+ @slug_delimiter = "-"
38
+ @perform_caching = Rails.configuration.action_controller.perform_caching
39
+ @contentful_options = {}
24
40
  end
25
41
  end
26
42
  end
@@ -0,0 +1,57 @@
1
+ module ContentfulRails
2
+ module Caching
3
+ # A module to prepend into ContentfulModel::Base which will allow the model instance
4
+ # to check the cache for its timestamp before making an expensive API call.
5
+ # Also includes a module method to remove an existing timestamp.
6
+ module Timestamps
7
+ def self.included(base)
8
+ base.extend ClassMethods
9
+ base.class_eval do
10
+ alias_method_chain :updated_at, :caching
11
+ alias_method_chain :cache_key, :preview
12
+ end
13
+ end
14
+
15
+ module ClassMethods
16
+ # Clear an existing timestamp from the cache; called by the subscriber to the Entry notifications
17
+ # from the WebhooksController.
18
+ def clear_cache_for(item_id)
19
+ cache_key = timestamp_cache_key(item_id)
20
+
21
+ Rails.cache.delete(cache_key)
22
+ end
23
+
24
+ def timestamp_cache_key(item_id)
25
+ "contentful_timestamp/#{self.content_type_id}/#{item_id}"
26
+ end
27
+ end
28
+
29
+
30
+ # A replacement method for updated_at(), called when this module is included in ContentfulModel::Base
31
+ def updated_at_with_caching
32
+ if ContentfulRails.configuration.perform_caching && !ContentfulModel.use_preview_api
33
+ Rails.cache.fetch(self.timestamp_cache_key) do
34
+ updated_at_without_caching
35
+ end
36
+ else
37
+ updated_at_without_caching
38
+ end
39
+ end
40
+
41
+ def timestamp_cache_key
42
+ self.class.timestamp_cache_key(id)
43
+ end
44
+
45
+ def cache_key_with_preview
46
+ if ContentfulModel.use_preview_api
47
+ "preview/#{cache_key_without_preview}"
48
+ else
49
+ cache_key_without_preview
50
+ end
51
+ end
52
+
53
+
54
+ end
55
+ end
56
+ end
57
+
@@ -3,10 +3,25 @@ module ContentfulRails
3
3
 
4
4
  isolate_namespace ContentfulRails
5
5
 
6
+ config.before_initialize do
7
+ if ContentfulRails.configuration.nil?
8
+ ContentfulRails.configure {}
9
+ end
10
+ end
11
+
12
+ initializer "configure_contentful", before: :add_entry_mappings do
13
+ ContentfulModel.configure do |config|
14
+ config.access_token = ContentfulRails.configuration.access_token
15
+ config.preview_access_token = ContentfulRails.configuration.preview_access_token
16
+ config.space = ContentfulRails.configuration.space
17
+ config.options = ContentfulRails.configuration.contentful_options
18
+ end
19
+ end
20
+
6
21
  #Iterate through all models which inherit from ContentfulModel::Base
7
22
  #and add an entry mapping for them, so calls to the Contentful API return
8
- #the appropriate classes.
9
- initializer "add_entry_mappings_for_contentful_models" do
23
+ #the appropriate classes
24
+ initializer "add_entry_mappings", after: :configure_contentful do
10
25
  if defined?(ContentfulModel)
11
26
  Rails.application.eager_load!
12
27
  ContentfulModel::Base.descendents.each do |klass|
@@ -15,22 +30,29 @@ module ContentfulRails
15
30
  end
16
31
  end
17
32
 
33
+ initializer "subscribe_to_webhook_events", after: :add_entry_mappings do
34
+ ActiveSupport::Notifications.subscribe(/Contentful.*Entry.*/) do |name, start, finish, id, payload|
35
+ content_type_id = payload[:sys][:contentType][:sys][:id]
36
+ klass = ContentfulModel.configuration.entry_mapping[content_type_id]
37
+ klass.send(:clear_cache_for, payload[:sys][:id])
38
+ end
39
+ end
40
+
18
41
  initializer "add_contentful_mime_type" do
19
42
  Mime::Type.register "application/json", :json, ["application/vnd.contentful.management.v1+json"]
20
43
  end
21
44
 
22
- config.to_prepare do
23
- if defined?(::ContentfulModel)
24
- ContentfulModel::Base.send(:include, ContentfulRails::CachedTimestamps)
45
+ initializer "add_preview_support" do
46
+ ActiveSupport.on_load(:action_controller) do
47
+ include ContentfulRails::Preview
25
48
  end
26
49
  end
27
50
 
28
- #if we're at the end of initialization and there's no config object,
29
- #set one up with the default options (i.e. an empty proc)
30
- config.after_initialize do
31
- if ContentfulRails.configuration.nil?
32
- ContentfulRails.configure {}
51
+ config.to_prepare do
52
+ if defined?(::ContentfulModel)
53
+ ContentfulModel::Base.send(:include, ContentfulRails::Caching::Timestamps)
33
54
  end
34
55
  end
56
+
35
57
  end
36
58
  end
@@ -5,6 +5,7 @@ require 'redcarpet'
5
5
  # You can subclass this in your application, to add or manipulate specific markup to elements in the markdown.
6
6
  class ContentfulRails::MarkdownRenderer < Redcarpet::Render::HTML
7
7
  include ActionView::Helpers::TagHelper
8
+ include ActionView::Context
8
9
  def initialize(opts)
9
10
  @options = opts
10
11
  @image_parameters = {
@@ -11,11 +11,15 @@ module ContentfulRails
11
11
  # e.g. /grandparent/parent/child
12
12
  # @param [Symbol] the field to search by - for example, :slug
13
13
  # @param [String] the path as a forward-slash separated string
14
- def get_nested_from_path_by(field, path, opts)
15
- if opts.present? && opts[:unescape]
16
- path = CGI::unescape(path)
17
- end
18
- root, *children = path.gsub(/^\//, '').split("/")
14
+ def get_nested_from_path_by(field, path, opts = {})
15
+ options = {delimiter: '/', unescape: false, prefix: ""}
16
+ options.merge!(opts)
17
+
18
+ path = CGI::unescape(path) if options[:unescape]
19
+ delimiter = options[:delimiter]
20
+ prefix = options[:prefix].empty? ? "" : "#{delimiter}#{options[:prefix]}#{delimiter}"
21
+
22
+ root, *children = "#{prefix}#{path}".gsub(/^\//, '').split(delimiter)
19
23
 
20
24
  if field.to_sym == :id
21
25
  #we need to call find() to get by ID
@@ -62,8 +66,13 @@ module ContentfulRails
62
66
  # @param [Symbol] the field to use to create the path
63
67
  # @param [String] the delimiter to use. Defaults to "/"
64
68
  # @return [String] the path as a string
65
- def nested_path_by(field, delimiter="/")
66
- ([self] + ancestors).reverse.collect {|a| a.send(field)}.join(delimiter)
69
+ def nested_path_by(field, opts = {})
70
+ options = {delimiter: "/", prefix: ""}
71
+ options.merge!(opts)
72
+ delimiter = options[:delimiter]
73
+ prefix = options[:prefix].empty? ? "" : "#{options[:prefix]}#{delimiter}"
74
+ path = ([self] + ancestors).reverse.collect {|a| a.send(field)}.join(delimiter).gsub(prefix,"")
75
+ return delimiter + path
67
76
  end
68
77
  end
69
- end
78
+ end
@@ -0,0 +1,53 @@
1
+ module ContentfulRails
2
+ module Preview
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ before_action :check_preview_domain
7
+ after_action :remove_preview_cache
8
+ helper_method :preview?
9
+ end
10
+ # Check whether the subdomain being presented is the preview domain.
11
+ # If so, set ContentfulModel to use the preview API, and request a username / password
12
+ def check_preview_domain
13
+ # If enable_preview_domain is not enabled, explicitly set use_preview_api false and return
14
+ unless ContentfulRails.configuration.enable_preview_domain
15
+ ContentfulModel.use_preview_api = false
16
+ return
17
+ end
18
+
19
+ #check subdomain matches the configured one - we assume it's first sub.domain.in.the.array
20
+ if request.subdomains.first == ContentfulRails.configuration.preview_domain
21
+ authenticated = authenticate_with_http_basic do |u,p|
22
+ u == ContentfulRails.configuration.preview_username
23
+ p == ContentfulRails.configuration.preview_password
24
+ end
25
+ # If user is authenticated, we're good to switch to the preview api
26
+ if authenticated
27
+ ContentfulModel.use_preview_api = true
28
+ else
29
+ #otherwise ask for user / pass
30
+ request_http_basic_authentication
31
+ end
32
+ else
33
+ #if the subdomain doesn't match the configured one, explicitly set to false
34
+ ContentfulModel.use_preview_api = false
35
+ return
36
+ end
37
+
38
+ end
39
+
40
+ # If we're in preview mode, we need to remove the preview view caches which were created.
41
+ # this is a bit of a hack but it's probably not feasible to turn off caching in preview mode.
42
+ def remove_preview_cache
43
+ # in preview mode, we alias_method_chain the cache_key method on ContentfulModel::Base to append 'preview/'
44
+ # to the front of the key.
45
+ return unless request.subdomain == ContentfulRails.configuration.preview_domain
46
+ expire_fragment(%r{.*/preview/.*})
47
+ end
48
+
49
+ def preview?
50
+ ContentfulModel.use_preview_api == true
51
+ end
52
+ end
53
+ end
@@ -1,19 +1,17 @@
1
1
  module ContentfulRails
2
2
  module Sluggable
3
+ extend ActiveSupport::Concern
3
4
  # A quick mixin to slugify a field other than 'slug'
4
5
  # NOTE that if you include sluggable (and define a slug field) in a class which responds to
5
6
  # slug() than you'll get a stack level too deep error.
6
- module Sluggable
7
- extend ActiveSupport::Concern
8
7
 
9
- class_methods do
10
- attr_accessor :slug_field
11
- end
8
+ class_methods do
9
+ attr_accessor :slug_field
10
+ end
12
11
 
13
- def slug
14
- if self.class.slug_field.present?
15
- self.send(self.class.slug_field).parameterize(Rails.configuration.x.param_delimiter)
16
- end
12
+ def slug
13
+ if self.class.slug_field.present?
14
+ self.send(self.class.slug_field).parameterize(ContentfulRails.configuration.slug_delimiter)
17
15
  end
18
16
  end
19
17
  end
@@ -1,3 +1,3 @@
1
1
  module ContentfulRails
2
- VERSION = "0.0.9"
2
+ VERSION = "0.2.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: contentful_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Error Creative Studio
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-22 00:00:00.000000000 Z
11
+ date: 2015-04-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: contentful_model
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '>='
18
18
  - !ruby/object:Gem::Version
19
- version: 0.1.5
19
+ version: 0.1.6
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '>='
25
25
  - !ruby/object:Gem::Version
26
- version: 0.1.5
26
+ version: 0.1.6
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rails
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -65,11 +65,12 @@ files:
65
65
  - app/helpers/contentful_rails/markdown_helper.rb
66
66
  - config/routes.rb
67
67
  - lib/contentful_rails.rb
68
- - lib/contentful_rails/cached_timestamps.rb
68
+ - lib/contentful_rails/caching/timestamps.rb
69
69
  - lib/contentful_rails/development_constraint.rb
70
70
  - lib/contentful_rails/engine.rb
71
71
  - lib/contentful_rails/markdown_renderer.rb
72
72
  - lib/contentful_rails/nested_resource.rb
73
+ - lib/contentful_rails/preview.rb
73
74
  - lib/contentful_rails/sluggable.rb
74
75
  - lib/contentful_rails/version.rb
75
76
  - lib/tasks/contentful_rails_tasks.rake
@@ -1,28 +0,0 @@
1
- module ContentfulRails
2
- #A module to prepend into ContentfulModel::Base which will allow the model instance
3
- #to check the cache for its timestamp before making an expensive API call
4
- module CachedTimestamps
5
- def self.included(base)
6
- base.class_eval do
7
- alias_method_chain :updated_at, :caching
8
- end
9
- end
10
-
11
- def updated_at_with_caching
12
- if Rails.configuration.action_controller.perform_caching
13
- Rails.cache.fetch(self.timestamp_cache_key) do
14
- updated_at_without_caching
15
- end
16
- else
17
- updated_at_without_caching
18
- end
19
- end
20
-
21
- def timestamp_cache_key
22
- "contentful_timestamp/#{self.class.content_type_id}/#{self.id}"
23
- end
24
-
25
- end
26
-
27
- end
28
-