contentful_rails 0.0.9 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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
-