pagelet_rails 0.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.
Files changed (33) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +402 -0
  4. data/Rakefile +37 -0
  5. data/app/assets/config/pagelet_rails_manifest.js +0 -0
  6. data/app/assets/javascripts/pagelet_rails/jquery.ajaxprogress.js +76 -0
  7. data/app/assets/javascripts/pagelet_rails.js +185 -0
  8. data/app/assets/javascripts/views/modal_dialog.jst.ejs +13 -0
  9. data/app/assets/javascripts/views/modal_dialog_iframe.jst.ejs +7 -0
  10. data/app/assets/javascripts/views/pagelet_load_failed.jst.ejs +7 -0
  11. data/app/assets/javascripts/views/pagelet_loading_overlay.jst.ejs +15 -0
  12. data/app/controllers/pagelet_controller.rb +4 -0
  13. data/app/controllers/pagelet_proxy_controller.rb +20 -0
  14. data/app/helpers/pagelets_helper.rb +82 -0
  15. data/app/views/layouts/pagelet_rails/container.html.slim +24 -0
  16. data/app/views/layouts/pagelet_rails/inner.slim +1 -0
  17. data/app/views/layouts/pagelet_rails/loading_placeholder.slim +14 -0
  18. data/config/routes.rb +7 -0
  19. data/lib/action_controller/action_caching.rb +16 -0
  20. data/lib/action_controller/caching/actions.rb +210 -0
  21. data/lib/pagelet_rails/concerns/cache.rb +65 -0
  22. data/lib/pagelet_rails/concerns/controller.rb +73 -0
  23. data/lib/pagelet_rails/concerns/options.rb +76 -0
  24. data/lib/pagelet_rails/concerns/placeholder.rb +35 -0
  25. data/lib/pagelet_rails/concerns/response_wrapper.rb +33 -0
  26. data/lib/pagelet_rails/concerns/routes.rb +83 -0
  27. data/lib/pagelet_rails/encryptor.rb +49 -0
  28. data/lib/pagelet_rails/engine.rb +4 -0
  29. data/lib/pagelet_rails/router.rb +23 -0
  30. data/lib/pagelet_rails/version.rb +3 -0
  31. data/lib/pagelet_rails.rb +28 -0
  32. data/lib/tasks/pagelet_rails_tasks.rake +4 -0
  33. metadata +104 -0
@@ -0,0 +1,185 @@
1
+ //= require_tree ./views
2
+ //= require pagelet_rails/jquery.ajaxprogress
3
+
4
+ (function (w) {
5
+
6
+ var root = w['PageletRails'] || {};
7
+ w['PageletRails'] = root;
8
+
9
+ root.addParamsToUrl = function( url, data ) {
10
+ if ( ! $.isEmptyObject(data) ) {
11
+ url += ( url.indexOf('?') >= 0 ? '&' : '?' ) + $.param(data);
12
+ }
13
+ return url;
14
+ };
15
+
16
+ root.appendScriptTag = function (text) {
17
+ var script = document.createElement( "script" );
18
+ script.type = "text/javascript";
19
+ script.text = text;
20
+ $("body").append(script);
21
+ };
22
+
23
+ root.loadDirectly = function(data) {
24
+ $.ajax({
25
+ url: data.url,
26
+ dataType: 'script',
27
+ headers: {
28
+ 'X-Pagelet': 'pagelet'
29
+ }
30
+ }).done(function(_) {
31
+ }).fail(function(){
32
+ var html = JST['views/pagelet_load_failed']({
33
+ pagelet_url: data.url,
34
+ reload_function: "PageletRails.loadPagelets('#" + data.id + "');"
35
+ });
36
+ data.elem.html(html)
37
+ });
38
+ };
39
+
40
+ root.loadThroughBatchProxy = function(urls) {
41
+ if (urls.length == 0) { return; }
42
+
43
+ var prev_index = 0;
44
+
45
+ $.ajax({
46
+ url: '/pagelet_proxy',
47
+ data: {
48
+ urls: urls
49
+ },
50
+ dataType: 'text',
51
+ cache: false,
52
+ headers: {
53
+ 'X-Pagelet': 'pagelet'
54
+ },
55
+ progress: function(_, progressEvent) {
56
+ var text = progressEvent.target.responseText;
57
+ var end_index = -1;
58
+
59
+ do {
60
+ end_index = text.indexOf("\n\n//\n\n", prev_index);
61
+
62
+ if (end_index != -1) {
63
+ var new_text = text.substring(prev_index, end_index);
64
+
65
+ eval(new_text);
66
+
67
+ prev_index = end_index + 1;
68
+ // console.log('found');
69
+ // console.log(new_text);
70
+ }
71
+
72
+ } while (end_index != -1);
73
+ }
74
+ });
75
+ };
76
+
77
+ root.loadPagelets = function(selector) {
78
+ selector = selector || '[data-widget-url]';
79
+ var groups = {};
80
+
81
+ $(selector).each(function(index, elem) {
82
+ var $el = $(elem);
83
+ var path = $el.data('widget-url');
84
+ var group = $el.data('pagelet-group');
85
+ var id = $el.attr('id');
86
+
87
+ var url = root.addParamsToUrl(path, {
88
+ target_container: id,
89
+ original_pagelet_options: $el.data('pagelet-options')
90
+ });
91
+
92
+ groups[group] = groups[group] || [];
93
+ groups[group].push({
94
+ id: id,
95
+ elem: $el,
96
+ url: url,
97
+ group: group
98
+ });
99
+ });
100
+
101
+ for (var group_name in groups) {
102
+ if (groups.hasOwnProperty(group_name)) {
103
+ var group = groups[group_name];
104
+
105
+ if (group.length == 1) {
106
+ root.loadDirectly(group[0]);
107
+ } else {
108
+ var urls = group.map(function(e) { return e.url; });
109
+ root.loadThroughBatchProxy(urls);
110
+ }
111
+ }
112
+ }
113
+ };
114
+
115
+ root.pageletArrived = function(id, content) {
116
+ root.placeToContainer(id, content);
117
+ root.processDataRemoteTags();
118
+ $(document).trigger('pagelet-loaded');
119
+ };
120
+
121
+ root.placeToContainer = function(id, content) {
122
+ $('#' + id).html(content);
123
+ };
124
+
125
+ root.processDataRemoteTags = function() {
126
+ $('form[data-remote]').each(function(index, elem){
127
+ var $el = $(elem);
128
+ var container = $el.closest('[data-pagelet-container]');
129
+
130
+ if (!container) {
131
+ return;
132
+ }
133
+
134
+ var hidden_field = $el.find('input[name=target_container]')[0];
135
+ if (!hidden_field) {
136
+ $("<input/>", {
137
+ name: "target_container",
138
+ type: "hidden",
139
+ value: container.attr('id')
140
+ }).appendTo($el);
141
+ }
142
+
143
+ hidden_field = $el.find('input[name=original_pagelet_options]')[0];
144
+ if (!hidden_field) {
145
+ $("<input/>", {
146
+ name: "original_pagelet_options",
147
+ type: "hidden",
148
+ value: container.data('pagelet-options')
149
+ }).appendTo($el);
150
+ }
151
+ });
152
+
153
+ var selector = 'a[data-remote]:not([disabled]),button[data-remote]:not([disabled])';
154
+ $(selector).each(function(index, elem){
155
+ var $el = $(elem);
156
+ var container = $el.closest('[data-pagelet-container]');
157
+
158
+ if (!container) {
159
+ return;
160
+ }
161
+
162
+ var params = $el.data('params');
163
+ if (!params) {
164
+ var value = $.param({
165
+ target_container: container.attr('id'),
166
+ original_pagelet_options: container.data('pagelet-options')
167
+ });
168
+ $el.data('params', value);
169
+ }
170
+ });
171
+ };
172
+
173
+ function initialise() {
174
+ document.addEventListener("turbolinks:load", function(){
175
+ root.loadPagelets();
176
+ root.processDataRemoteTags();
177
+ });
178
+ }
179
+
180
+ initialise();
181
+ })(window);
182
+
183
+
184
+
185
+
@@ -0,0 +1,13 @@
1
+ <div class="modal-dialog">
2
+ <div class="modal-content">
3
+ <div class="modal-body">
4
+ <% if (state == 'loading') { %>
5
+ <p>Loading...</p>
6
+ <% } %>
7
+
8
+ <% if (state == 'error') { %>
9
+ <p>This page could not be loaded. Please try again later.</p>
10
+ <% } %>
11
+ </div>
12
+ </div>
13
+ </div>
@@ -0,0 +1,7 @@
1
+ <div class="modal-dialog modal-lg">
2
+ <div class="modal-content">
3
+ <div class="modal-body">
4
+ <iframe src="<%= src %>" style="zoom:0.60" width="99.6%" height="0" frameborder="0"></iframe>
5
+ </div>
6
+ </div>
7
+ </div>
@@ -0,0 +1,7 @@
1
+ Error occurred during loading
2
+ <div class="debug">
3
+
4
+ <a href="<%= pagelet_url %>" target="_blank">Open in new tab</a>
5
+
6
+ <a href="javascript:<%= reload_function %>"> Reload </a>
7
+ </div>
@@ -0,0 +1,15 @@
1
+ <div class="pagelet-loading-overlay fade">
2
+ <div style="display: table; overflow: hidden; width: 100%; height:auto;">
3
+ <div style="display: table-cell; vertical-align: middle;">
4
+ <div class="pagelet-loading-overlay__content">
5
+ <span class="spinner spinner-three-bounce">
6
+ <div class="bounce1"></div>
7
+ <div class="bounce2"></div>
8
+ <div class="bounce3"></div>
9
+ </span>
10
+ <br>
11
+ <span>Loading...</span>
12
+ </div>
13
+ </div>
14
+ </div>
15
+ </div>
@@ -0,0 +1,4 @@
1
+ class PageletController < ::ApplicationController
2
+ include PageletRails::Concerns::Controller
3
+
4
+ end
@@ -0,0 +1,20 @@
1
+ class PageletProxyController < ::ApplicationController
2
+ include ActionController::Live
3
+ include PageletsHelper
4
+
5
+ def show
6
+ @urls = params[:urls]
7
+
8
+ response.headers['Content-Type'] = 'text/javascript'
9
+
10
+ response.stream.write "\n"
11
+
12
+ @urls.each do |url|
13
+ response.stream.write pagelet(url)
14
+ response.stream.write "\n\n//\n\n"
15
+ end
16
+ ensure
17
+ response.stream.close
18
+ end
19
+
20
+ end
@@ -0,0 +1,82 @@
1
+ module PageletsHelper
2
+
3
+ def pagelet_stream
4
+ return nil if pagelet_stream_objects.empty?
5
+ pagelet_stream_objects.each do |key, block|
6
+ concat content_tag('script', raw("PageletRails.pageletArrived('#{key}', '#{j capture(&block)}');\n"), type: 'text/javascript')
7
+ end
8
+ nil
9
+ end
10
+
11
+ def pagelet_default_id
12
+ "pagelet_#{rand(2**60).to_s(36)}"
13
+ end
14
+
15
+ def add_pagelet_stream key, &block
16
+ objects = pagelet_stream_objects
17
+ raise "duplicate key: #{key}" if objects.has_key?(key)
18
+ objects[key] = block
19
+ request.instance_variable_set(:@pagelet_stream_objects, objects)
20
+ end
21
+
22
+ def pagelet_stream_objects
23
+ request.instance_variable_get(:@pagelet_stream_objects) || {}
24
+ end
25
+
26
+ def pagelet path, p_options = {}
27
+ puts "Rendering pagelet #{path}".blue
28
+
29
+ p_params = p_options.delete(:params) { {} }.with_indifferent_access
30
+
31
+ if path.is_a? Symbol
32
+ path = self.send("#{path}_path", p_params)
33
+ else
34
+ uri = URI(path)
35
+ p_params.merge! Rack::Utils.parse_nested_query(uri.query)
36
+ p_options.merge! remote: false
37
+ end
38
+
39
+ path_opts = Rails.application.routes.recognize_path(path)
40
+ p_params.reverse_merge!(path_opts)
41
+
42
+ controller_class = path_opts[:controller].camelize.concat('Controller').constantize
43
+ action = path_opts[:action]
44
+
45
+
46
+ if p_options[:remote] == :stream
47
+ html_id = p_options.dig(:html, :id) || pagelet_default_id
48
+ p_options.deep_merge! html: { id: html_id }
49
+
50
+ add_pagelet_stream html_id, &Proc.new {
51
+ pagelet path, p_options.merge(remote: false, skip_container: true)
52
+ }
53
+ end
54
+
55
+ p_options.deep_merge! parent_params: params.to_h
56
+
57
+ c = controller_class.new
58
+ c.pagelet_options p_options
59
+ c.pagelet_options original_options: p_options
60
+
61
+ env = Rack::MockRequest.env_for(path,
62
+ 'REMOTE_ADDR' => request.env['REMOTE_ADDR'],
63
+ 'HTTP_HOST' => request.env['HTTP_HOST'],
64
+ 'HTTP_TURBOLINKS_REFERRER' => request.env['HTTP_TURBOLINKS_REFERRER'],
65
+ 'HTTP_USER_AGENT' => request.env['HTTP_USER_AGENT'],
66
+ 'HTTP_X_CSRF_TOKEN' => request.env['HTTP_X_CSRF_TOKEN'],
67
+ 'HTTP_X_PAGELET' => request.env['HTTP_X_PAGELET'],
68
+ 'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest",
69
+ )
70
+
71
+ p_request = ActionDispatch::Request.new(env)
72
+ p_request.parameters.clear
73
+ p_request.parameters.merge! p_params
74
+
75
+ p_response = controller_class.make_response! p_request
76
+ c.dispatch(action, p_request, p_response)
77
+
78
+ body = c.response.body
79
+ body.html_safe
80
+ end
81
+
82
+ end
@@ -0,0 +1,24 @@
1
+ - if pagelet_request? || pagelet_options.skip_container
2
+ = content_for?(:content) ? yield(:content) : yield
3
+
4
+ - else
5
+ ruby:
6
+ html_opts = pagelet_options.html || {}
7
+ classes = html_opts.fetch(:class, '').split(' ')
8
+ classes << "pagelet-#{controller_name}"
9
+ classes << "pagelet-#{controller_name}-#{action_name}"
10
+
11
+ html_opts[:id] ||= pagelet_default_id
12
+ html_opts[:class] = classes.join(' ')
13
+
14
+ html_opts['data-pagelet-container'] = true
15
+
16
+ encode_data = pagelet_options.original_options.to_h.except('remote')
17
+ html_opts['data-pagelet-options'] = PageletRails::Encryptor.encode(encode_data)
18
+
19
+ if pagelet_options.ajax_group
20
+ html_opts['data-pagelet-group'] = pagelet_options.ajax_group
21
+ end
22
+
23
+ div *html_opts
24
+ = content_for?(:content) ? yield(:content) : yield
@@ -0,0 +1 @@
1
+ = content_for?(:content) ? yield(:content) : yield
@@ -0,0 +1,14 @@
1
+ ruby:
2
+ height = pagelet_options.placeholder.try(:[], :height)
3
+ text = pagelet_options.placeholder.try(:[], :text) || 'Loading ...'
4
+ height = height.is_a?(Numeric) ? "#{height}px" : 'auto'
5
+
6
+ div style="display: table; height: #{height}; overflow: hidden; width: 100%;"
7
+ div style="display: table-cell; vertical-align: middle;"
8
+ div.text-center
9
+ span.spinner.spinner-three-bounce
10
+ .bounce1
11
+ .bounce2
12
+ .bounce3
13
+ br
14
+ span = text
data/config/routes.rb ADDED
@@ -0,0 +1,7 @@
1
+ Rails.application.routes.draw do
2
+
3
+ PageletRails::Router.load_routes!(self)
4
+
5
+ get 'pagelet_proxy' => 'pagelet_proxy#show'
6
+
7
+ end
@@ -0,0 +1,16 @@
1
+ # Cloned from https://github.com/rails/actionpack-action_caching
2
+ # as it does not support rails 5 yet
3
+
4
+ require 'action_controller/caching/actions'
5
+
6
+ module ActionController
7
+ module Caching
8
+ eager_autoload do
9
+ autoload :Actions
10
+ end
11
+
12
+ include Actions
13
+ end
14
+ end
15
+
16
+ ActionController::Base.send(:include, ActionController::Caching::Actions)
@@ -0,0 +1,210 @@
1
+ require 'set'
2
+
3
+ module ActionController
4
+ module Caching
5
+ # Action caching is similar to page caching by the fact that the entire
6
+ # output of the response is cached, but unlike page caching, every
7
+ # request still goes through Action Pack. The key benefit of this is
8
+ # that filters run before the cache is served, which allows for
9
+ # authentication and other restrictions on whether someone is allowed
10
+ # to execute such action.
11
+ #
12
+ # class ListsController < ApplicationController
13
+ # before_filter :authenticate, except: :public
14
+ #
15
+ # caches_page :public
16
+ # caches_action :index, :show
17
+ # end
18
+ #
19
+ # In this example, the +public+ action doesn't require authentication
20
+ # so it's possible to use the faster page caching. On the other hand
21
+ # +index+ and +show+ require authentication. They can still be cached,
22
+ # but we need action caching for them.
23
+ #
24
+ # Action caching uses fragment caching internally and an around
25
+ # filter to do the job. The fragment cache is named according to
26
+ # the host and path of the request. A page that is accessed at
27
+ # <tt>http://david.example.com/lists/show/1</tt> will result in a fragment named
28
+ # <tt>david.example.com/lists/show/1</tt>. This allows the cacher to
29
+ # differentiate between <tt>david.example.com/lists/</tt> and
30
+ # <tt>jamis.example.com/lists/</tt> -- which is a helpful way of assisting
31
+ # the subdomain-as-account-key pattern.
32
+ #
33
+ # Different representations of the same resource, e.g.
34
+ # <tt>http://david.example.com/lists</tt> and
35
+ # <tt>http://david.example.com/lists.xml</tt>
36
+ # are treated like separate requests and so are cached separately.
37
+ # Keep in mind when expiring an action cache that
38
+ # <tt>action: 'lists'</tt> is not the same as
39
+ # <tt>action: 'lists', format: :xml</tt>.
40
+ #
41
+ # You can modify the default action cache path by passing a
42
+ # <tt>:cache_path</tt> option. This will be passed directly to
43
+ # <tt>ActionCachePath.new</tt>. This is handy for actions with
44
+ # multiple possible routes that should be cached differently. If a
45
+ # block is given, it is called with the current controller instance.
46
+ # If an object that responds to <tt>call</tt> is given, it'll be called
47
+ # with the current controller instance.
48
+ #
49
+ # And you can also use <tt>:if</tt> (or <tt>:unless</tt>) to pass a
50
+ # proc that specifies when the action should be cached.
51
+ #
52
+ # As of Rails 3.0, you can also pass <tt>:expires_in</tt> with a time
53
+ # interval (in seconds) to schedule expiration of the cached item.
54
+ #
55
+ # The following example depicts some of the points made above:
56
+ #
57
+ # class CachePathCreator
58
+ # def initialize(name)
59
+ # @name = name
60
+ # end
61
+ #
62
+ # def call(controller)
63
+ # "cache-path-#{@name}"
64
+ # end
65
+ # end
66
+ #
67
+ #
68
+ # class ListsController < ApplicationController
69
+ # before_filter :authenticate, except: :public
70
+ #
71
+ # caches_page :public
72
+ #
73
+ # caches_action :index, if: Proc.new do
74
+ # !request.format.json? # cache if is not a JSON request
75
+ # end
76
+ #
77
+ # caches_action :show, cache_path: { project: 1 },
78
+ # expires_in: 1.hour
79
+ #
80
+ # caches_action :feed, cache_path: Proc.new do
81
+ # if params[:user_id]
82
+ # user_list_url(params[:user_id, params[:id])
83
+ # else
84
+ # list_url(params[:id])
85
+ # end
86
+ # end
87
+ #
88
+ # caches_action :posts, cache_path: CachePathCreator.new('posts')
89
+ # end
90
+ #
91
+ # If you pass <tt>layout: false</tt>, it will only cache your action
92
+ # content. That's useful when your layout has dynamic information.
93
+ #
94
+ # Warning: If the format of the request is determined by the Accept HTTP
95
+ # header the Content-Type of the cached response could be wrong because
96
+ # no information about the MIME type is stored in the cache key. So, if
97
+ # you first ask for MIME type M in the Accept header, a cache entry is
98
+ # created, and then perform a second request to the same resource asking
99
+ # for a different MIME type, you'd get the content cached for M.
100
+ #
101
+ # The <tt>:format</tt> parameter is taken into account though. The safest
102
+ # way to cache by MIME type is to pass the format in the route.
103
+ module Actions
104
+ extend ActiveSupport::Concern
105
+
106
+ module ClassMethods
107
+ # Declares that +actions+ should be cached.
108
+ # See ActionController::Caching::Actions for details.
109
+ def caches_action(*actions)
110
+ return unless cache_configured?
111
+ options = actions.extract_options!
112
+ options[:layout] = true unless options.key?(:layout)
113
+ filter_options = options.extract!(:if, :unless).merge(only: actions)
114
+ cache_options = options.extract!(:layout, :cache_path).merge(store_options: options)
115
+
116
+ around_filter ActionCacheFilter.new(cache_options), filter_options
117
+ end
118
+ end
119
+
120
+ def _save_fragment(name, options)
121
+ content = ''
122
+ response_body.each do |parts|
123
+ content << parts
124
+ end
125
+
126
+ if caching_allowed?
127
+ write_fragment(name, content, options)
128
+ else
129
+ content
130
+ end
131
+ end
132
+
133
+ def caching_allowed?
134
+ (request.get? || request.head?) && response.status == 200
135
+ end
136
+
137
+ protected
138
+ def expire_action(options = {})
139
+ return unless cache_configured?
140
+
141
+ if options.is_a?(Hash) && options[:action].is_a?(Array)
142
+ options[:action].each { |action| expire_action(options.merge(action: action)) }
143
+ else
144
+ expire_fragment(ActionCachePath.new(self, options, false).path)
145
+ end
146
+ end
147
+
148
+ class ActionCacheFilter # :nodoc:
149
+ def initialize(options, &block)
150
+ @cache_path, @store_options, @cache_layout =
151
+ options.values_at(:cache_path, :store_options, :layout)
152
+ end
153
+
154
+ def around(controller)
155
+ cache_layout = @cache_layout.respond_to?(:call) ? @cache_layout.call(controller) : @cache_layout
156
+
157
+ path_options = if @cache_path.is_a?(Proc)
158
+ controller.instance_exec(controller, &@cache_path)
159
+ elsif @cache_path.respond_to?(:call)
160
+ @cache_path.call(controller)
161
+ else
162
+ @cache_path
163
+ end
164
+
165
+ cache_path = ActionCachePath.new(controller, path_options || {})
166
+
167
+ body = controller.read_fragment(cache_path.path, @store_options)
168
+
169
+ unless body
170
+ controller.action_has_layout = false unless cache_layout
171
+ yield
172
+ controller.action_has_layout = true
173
+ body = controller._save_fragment(cache_path.path, @store_options)
174
+ end
175
+
176
+ body = controller.render_to_string(body: body, layout: true) unless cache_layout
177
+
178
+ controller.response_body = body
179
+ controller.content_type = Mime[cache_path.extension || :html]
180
+ end
181
+ end
182
+
183
+ class ActionCachePath
184
+ attr_reader :path, :extension
185
+
186
+ # If +infer_extension+ is +true+, the cache path extension is looked up from the request's
187
+ # path and format. This is desirable when reading and writing the cache, but not when
188
+ # expiring the cache - +expire_action+ should expire the same files regardless of the
189
+ # request format.
190
+ def initialize(controller, options = {}, infer_extension = true)
191
+ if infer_extension
192
+ @extension = controller.params[:format]
193
+ options.reverse_merge!(format: @extension) if options.is_a?(Hash)
194
+ end
195
+
196
+ path = controller.url_for(options).split('://', 2).last
197
+ @path = normalize!(path)
198
+ end
199
+
200
+ private
201
+ def normalize!(path)
202
+ ext = URI.parser.escape(extension) if extension
203
+ path << 'index' if path[-1] == ?/
204
+ path << ".#{ext}" if extension and !path.split('?', 2).first.ends_with?(".#{ext}")
205
+ URI.parser.unescape(path)
206
+ end
207
+ end
208
+ end
209
+ end
210
+ end
@@ -0,0 +1,65 @@
1
+ module PageletRails::Concerns::Cache
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ include ActionController::Caching::Actions
6
+
7
+ pagelet_options cache_defaults: {
8
+ expires_in: 5.seconds,
9
+ cache_path: {}
10
+ }
11
+
12
+ around_action :pagelet_cache
13
+ end
14
+
15
+ def pagelet_cache &block
16
+ # puts 'pagelet_cache'.blue
17
+ cache_enabled = pagelet_options.cache || pagelet_options.cache_path || pagelet_options.expires_in
18
+
19
+ if !cache_enabled
20
+ return yield
21
+ end
22
+
23
+ cache_defaults = (pagelet_options.cache_defaults || {}).to_h.symbolize_keys
24
+ store_options = cache_defaults.except(:cache_path)
25
+ store_options[:expires_in] = pagelet_options.expires_in if pagelet_options.expires_in
26
+
27
+ cache_path = pagelet_options.cache_path || cache_defaults[:cache_path]
28
+
29
+ cache_path = if cache_path.is_a?(Proc)
30
+ self.instance_exec(self, &cache_path)
31
+ elsif cache_path.respond_to?(:call)
32
+ cache_path.call(self)
33
+ elsif cache_path.is_a?(String)
34
+ {
35
+ custom: cache_path
36
+ }
37
+ else
38
+ cache_path
39
+ end
40
+ cache_path ||= {}
41
+ cache_path[:controller] = params[:controller]
42
+ cache_path[:action] = params[:action]
43
+
44
+ path_object = ActionController::Caching::Actions::ActionCachePath.new(self, cache_path)
45
+ has_cache = fragment_exist?(path_object.path, store_options)
46
+ pagelet_options has_cache: has_cache
47
+
48
+
49
+ if (pagelet_render_remotely? && has_cache) || !pagelet_render_remotely?
50
+ cache_options = {
51
+ layout: false,
52
+ store_options: store_options,
53
+ cache_path: cache_path
54
+ }
55
+
56
+ filter = ActionController::Caching::Actions::ActionCacheFilter.new(cache_options)
57
+
58
+ filter.around(self, &block)
59
+
60
+ else
61
+ yield
62
+ end
63
+ end
64
+
65
+ end