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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +402 -0
- data/Rakefile +37 -0
- data/app/assets/config/pagelet_rails_manifest.js +0 -0
- data/app/assets/javascripts/pagelet_rails/jquery.ajaxprogress.js +76 -0
- data/app/assets/javascripts/pagelet_rails.js +185 -0
- data/app/assets/javascripts/views/modal_dialog.jst.ejs +13 -0
- data/app/assets/javascripts/views/modal_dialog_iframe.jst.ejs +7 -0
- data/app/assets/javascripts/views/pagelet_load_failed.jst.ejs +7 -0
- data/app/assets/javascripts/views/pagelet_loading_overlay.jst.ejs +15 -0
- data/app/controllers/pagelet_controller.rb +4 -0
- data/app/controllers/pagelet_proxy_controller.rb +20 -0
- data/app/helpers/pagelets_helper.rb +82 -0
- data/app/views/layouts/pagelet_rails/container.html.slim +24 -0
- data/app/views/layouts/pagelet_rails/inner.slim +1 -0
- data/app/views/layouts/pagelet_rails/loading_placeholder.slim +14 -0
- data/config/routes.rb +7 -0
- data/lib/action_controller/action_caching.rb +16 -0
- data/lib/action_controller/caching/actions.rb +210 -0
- data/lib/pagelet_rails/concerns/cache.rb +65 -0
- data/lib/pagelet_rails/concerns/controller.rb +73 -0
- data/lib/pagelet_rails/concerns/options.rb +76 -0
- data/lib/pagelet_rails/concerns/placeholder.rb +35 -0
- data/lib/pagelet_rails/concerns/response_wrapper.rb +33 -0
- data/lib/pagelet_rails/concerns/routes.rb +83 -0
- data/lib/pagelet_rails/encryptor.rb +49 -0
- data/lib/pagelet_rails/engine.rb +4 -0
- data/lib/pagelet_rails/router.rb +23 -0
- data/lib/pagelet_rails/version.rb +3 -0
- data/lib/pagelet_rails.rb +28 -0
- data/lib/tasks/pagelet_rails_tasks.rake +4 -0
- metadata +104 -0
@@ -0,0 +1,73 @@
|
|
1
|
+
module PageletRails::Concerns::Controller
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
# order is important
|
6
|
+
include PageletRails::Concerns::ResponseWrapper
|
7
|
+
include PageletRails::Concerns::Routes
|
8
|
+
include PageletRails::Concerns::Options
|
9
|
+
include PageletRails::Concerns::Cache
|
10
|
+
include PageletRails::Concerns::Placeholder
|
11
|
+
|
12
|
+
prepend_before_action :merge_original_pagelet_options
|
13
|
+
prepend_before_action :append_pagelet_view_paths
|
14
|
+
|
15
|
+
layout :layout_name
|
16
|
+
|
17
|
+
helper_method :pagelet_request?
|
18
|
+
|
19
|
+
pagelet_options layout: 'panel'
|
20
|
+
end
|
21
|
+
|
22
|
+
def layout_name
|
23
|
+
layout = params[:layout] || pagelet_options.layout
|
24
|
+
|
25
|
+
"pagelets/#{layout}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def pagelet_request?
|
29
|
+
request.headers['X-Pagelet'].present? || params[:target_container]
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def append_pagelet_view_paths
|
35
|
+
self.view_paths.unshift 'app/pagelets/'
|
36
|
+
|
37
|
+
# lookup_context.prefixes.clear
|
38
|
+
view = "#{controller_name}/views"
|
39
|
+
if lookup_context.prefixes.exclude?(view)
|
40
|
+
lookup_context.prefixes.unshift "#{controller_name}/views"
|
41
|
+
end
|
42
|
+
|
43
|
+
# https://github.com/rails/actionpack-action_caching/issues/32
|
44
|
+
if lookup_context.formats.exclude?(:html)
|
45
|
+
lookup_context.formats.unshift :html
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def merge_original_pagelet_options
|
50
|
+
if params[:original_pagelet_options]
|
51
|
+
opts = PageletRails::Encryptor.decode(params[:original_pagelet_options])
|
52
|
+
pagelet_options(opts)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def pagelet_render_remotely?
|
57
|
+
case pagelet_options.remote
|
58
|
+
when :stream
|
59
|
+
render_remotely = true
|
60
|
+
when :turbolinks
|
61
|
+
# render now if request coming from turbolinks
|
62
|
+
is_turbolinks_request = request.headers['Turbolinks-Referrer'].present?
|
63
|
+
render_remotely = !is_turbolinks_request
|
64
|
+
when true, :ajax
|
65
|
+
render_remotely = true
|
66
|
+
else
|
67
|
+
render_remotely = false
|
68
|
+
end
|
69
|
+
|
70
|
+
render_remotely
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module PageletRails::Concerns::Options
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
include Shared
|
6
|
+
|
7
|
+
helper_method :pagelet_options
|
8
|
+
end
|
9
|
+
|
10
|
+
def pagelet_options *args
|
11
|
+
set_pagelet_options *args
|
12
|
+
|
13
|
+
opts = self.class.pagelet_options
|
14
|
+
class_default_opts = opts.fetch('default', {})
|
15
|
+
class_action_opts = opts.fetch(action_name, {})
|
16
|
+
|
17
|
+
instance_default_opts = @pagelet_options.fetch('default', {})
|
18
|
+
instance_action_opts = @pagelet_options.fetch(action_name, {})
|
19
|
+
|
20
|
+
result = {}.with_indifferent_access
|
21
|
+
.deep_merge!(class_default_opts)
|
22
|
+
.deep_merge!(class_action_opts)
|
23
|
+
.deep_merge!(instance_default_opts)
|
24
|
+
.deep_merge!(instance_action_opts)
|
25
|
+
|
26
|
+
OpenStruct.new result
|
27
|
+
end
|
28
|
+
|
29
|
+
module Shared
|
30
|
+
def set_pagelet_options *args
|
31
|
+
opts = args.extract_options!
|
32
|
+
actions = args
|
33
|
+
actions << 'default' if actions.blank?
|
34
|
+
|
35
|
+
@pagelet_options ||= {}.with_indifferent_access
|
36
|
+
|
37
|
+
if opts.any?
|
38
|
+
actions.each do |action|
|
39
|
+
@pagelet_options.deep_merge! action => opts
|
40
|
+
end
|
41
|
+
end
|
42
|
+
@pagelet_options
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
module ClassMethods
|
47
|
+
include Shared
|
48
|
+
|
49
|
+
def pagelet_options *args
|
50
|
+
set_pagelet_options *args
|
51
|
+
|
52
|
+
if superclass && superclass.instance_variable_defined?(:@pagelet_options)
|
53
|
+
parent = superclass.instance_variable_get :@pagelet_options
|
54
|
+
parent.merge(@pagelet_options)
|
55
|
+
else
|
56
|
+
@pagelet_options
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def inherited subklass
|
61
|
+
existing = subklass.ancestors.reverse.
|
62
|
+
reduce({}.with_indifferent_access) do |memo, ancestor|
|
63
|
+
|
64
|
+
if ancestor.instance_variable_defined?(:@pagelet_options)
|
65
|
+
memo.deep_merge! ancestor.instance_variable_get :@pagelet_options
|
66
|
+
end
|
67
|
+
memo
|
68
|
+
end
|
69
|
+
|
70
|
+
subklass.instance_variable_set(:@pagelet_options, existing)
|
71
|
+
|
72
|
+
super
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module PageletRails::Concerns::Placeholder
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
# This concern should be called after cache callback
|
5
|
+
# #process_action method does not give such order
|
6
|
+
# as it's called before callbacks
|
7
|
+
def send_action *args
|
8
|
+
render_remote_load
|
9
|
+
if !performed?
|
10
|
+
super
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def render_remote_load
|
15
|
+
# puts 'render_remote_load'.blue
|
16
|
+
render_remotely = pagelet_render_remotely?
|
17
|
+
if render_remotely && pagelet_options.has_cache
|
18
|
+
render_remotely = false
|
19
|
+
end
|
20
|
+
|
21
|
+
return unless render_remotely
|
22
|
+
|
23
|
+
data = params.deep_dup
|
24
|
+
data.permit!
|
25
|
+
|
26
|
+
if pagelet_options.remote != :stream
|
27
|
+
pagelet_options html: { 'data-widget-url' => url_for(data) }
|
28
|
+
end
|
29
|
+
|
30
|
+
default_view = '/layouts/pagelet_rails/loading_placeholder'
|
31
|
+
view = pagelet_options.placeholder.try(:[], :view).presence || default_view
|
32
|
+
|
33
|
+
render view
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module PageletRails::Concerns::ResponseWrapper
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
def process_action *args
|
5
|
+
super.tap do
|
6
|
+
if params[:target_container] &&
|
7
|
+
action_has_layout? &&
|
8
|
+
request.format.js? # wrap to js only if requested js
|
9
|
+
|
10
|
+
response.content_type = 'text/javascript'
|
11
|
+
|
12
|
+
html = self.response_body.reduce('') { |memo, body|
|
13
|
+
memo << body
|
14
|
+
memo
|
15
|
+
}
|
16
|
+
|
17
|
+
if html.match /^\s*</
|
18
|
+
# the body could be javascript, make sure it's html before wrapping
|
19
|
+
|
20
|
+
id = ActionController::Base.helpers.escape_javascript params[:target_container]
|
21
|
+
js = ActionController::Base.helpers.escape_javascript html
|
22
|
+
|
23
|
+
html = ActionController::Base.helpers.raw(
|
24
|
+
"PageletRails.pageletArrived('#{id}', '#{js}');"
|
25
|
+
)
|
26
|
+
|
27
|
+
self.response_body = [html]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module PageletRails::Concerns::Routes
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
module ClassMethods
|
5
|
+
# Define routes inline in controller
|
6
|
+
#
|
7
|
+
# pagelet_routes do
|
8
|
+
# resources :users
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
def pagelet_routes &block
|
12
|
+
@pagelet_routes << block
|
13
|
+
end
|
14
|
+
|
15
|
+
def pagelet_resources *args, &block
|
16
|
+
controller_name = self.controller_name
|
17
|
+
@pagelet_routes << Proc.new do
|
18
|
+
resources controller_name, *args, &block
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def pagelet_resource *args, &block
|
23
|
+
controller_name = self.controller_name
|
24
|
+
opts = args.extract_options!
|
25
|
+
opts[:controller] ||= controller_name
|
26
|
+
|
27
|
+
@pagelet_routes << Proc.new do
|
28
|
+
resource controller_name, *args, opts, &block
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Define inline single route for the following method.
|
33
|
+
# It automatically adds :controller and :action names to the route
|
34
|
+
#
|
35
|
+
# class PageletRails::Examples::ExamplesController
|
36
|
+
# pageletlet_route :get, ''
|
37
|
+
# def bingo
|
38
|
+
# end
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# will generate routes
|
42
|
+
# Helper: pagelets_examples_path
|
43
|
+
# HTTP Verb: GET
|
44
|
+
# Path: /pagelets/examples(.:format)
|
45
|
+
# Controller#Action: pagelets/examples/examples#bingo
|
46
|
+
#
|
47
|
+
def pagelet_route *args
|
48
|
+
@pagelet_route << args
|
49
|
+
end
|
50
|
+
|
51
|
+
def method_added method_name
|
52
|
+
return unless @pagelet_route
|
53
|
+
@pagelet_route.each do |args|
|
54
|
+
options = args.extract_options!
|
55
|
+
options[:controller] ||= self.controller_name
|
56
|
+
options[:action] ||= method_name
|
57
|
+
|
58
|
+
@pagelet_routes << Proc.new do
|
59
|
+
scope path: options[:controller], as: options[:controller] do
|
60
|
+
self.send *args, options
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
@pagelet_route = []
|
66
|
+
super
|
67
|
+
end
|
68
|
+
|
69
|
+
def load_pagelet_routes! context
|
70
|
+
@pagelet_routes.each do |proc|
|
71
|
+
context.instance_eval &proc
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def inherited subklass
|
76
|
+
subklass.instance_variable_set(:@pagelet_routes, [])
|
77
|
+
subklass.instance_variable_set(:@pagelet_route, [])
|
78
|
+
super
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
class PageletRails::Encryptor
|
2
|
+
|
3
|
+
DEFAULT_SALT = '!@#Q156^tdSXggT0&*789++8&?_|T%\/++==RqE'
|
4
|
+
|
5
|
+
attr_reader :salt
|
6
|
+
|
7
|
+
def self.encode(data, opts = {})
|
8
|
+
self.new(opts).encode data
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.decode(encrypted_data, opts = {})
|
12
|
+
self.new(opts).decode encrypted_data
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.get_key secret, salt
|
16
|
+
@get_key_cache ||= {}
|
17
|
+
key = [secret, salt]
|
18
|
+
|
19
|
+
@get_key_cache[key] ||= ActiveSupport::KeyGenerator.new(secret).generate_key(salt)
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(opts = {})
|
23
|
+
@salt = opts.fetch :salt, DEFAULT_SALT
|
24
|
+
@secret = opts[:secret]
|
25
|
+
end
|
26
|
+
|
27
|
+
def secret
|
28
|
+
@secret || Rails.application.secrets[:secret_key_base]
|
29
|
+
end
|
30
|
+
|
31
|
+
def encode(data)
|
32
|
+
encryptor.encrypt_and_sign(data)
|
33
|
+
end
|
34
|
+
|
35
|
+
def decode(encrypted_data)
|
36
|
+
encryptor.decrypt_and_verify(encrypted_data)
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def encryptor
|
42
|
+
@encryptor ||= begin
|
43
|
+
key = self.class.get_key secret, salt
|
44
|
+
|
45
|
+
ActiveSupport::MessageEncryptor.new(key)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class PageletRails::Router
|
2
|
+
|
3
|
+
def self.load_routes! context
|
4
|
+
controllers = Dir[Rails.root.join('app', 'pagelets', '*', '*controller.rb')]
|
5
|
+
|
6
|
+
controllers.each do |controller_file|
|
7
|
+
pagelet_name = File.basename(File.dirname(controller_file))
|
8
|
+
|
9
|
+
basename_controller_name = File.basename controller_file, '.rb'
|
10
|
+
controller = "#{pagelet_name}/#{basename_controller_name}".camelize.constantize
|
11
|
+
|
12
|
+
next unless controller.respond_to? :load_pagelet_routes!
|
13
|
+
|
14
|
+
context.instance_eval do
|
15
|
+
scope module: pagelet_name, path: "/pagelets", as: "pagelets" do
|
16
|
+
controller.load_pagelet_routes! self
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "pagelet_rails/engine"
|
2
|
+
require "pagelet_rails/version"
|
3
|
+
|
4
|
+
require "action_controller/action_caching"
|
5
|
+
|
6
|
+
|
7
|
+
module PageletRails
|
8
|
+
extend ActiveSupport::Autoload
|
9
|
+
|
10
|
+
eager_autoload do
|
11
|
+
autoload :Encryptor
|
12
|
+
autoload :Router
|
13
|
+
end
|
14
|
+
|
15
|
+
module Concerns
|
16
|
+
extend ActiveSupport::Autoload
|
17
|
+
|
18
|
+
eager_autoload do
|
19
|
+
autoload :Cache
|
20
|
+
autoload :Controller
|
21
|
+
autoload :Options
|
22
|
+
autoload :Placeholder
|
23
|
+
autoload :ResponseWrapper
|
24
|
+
autoload :Routes
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pagelet_rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Anton Katunin
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-08-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 5.0.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 5.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: sqlite3
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: Improve perceived performance of your rails application with minimum
|
42
|
+
effort
|
43
|
+
email:
|
44
|
+
- antulik@gmail.com
|
45
|
+
executables: []
|
46
|
+
extensions: []
|
47
|
+
extra_rdoc_files: []
|
48
|
+
files:
|
49
|
+
- MIT-LICENSE
|
50
|
+
- README.md
|
51
|
+
- Rakefile
|
52
|
+
- app/assets/config/pagelet_rails_manifest.js
|
53
|
+
- app/assets/javascripts/pagelet_rails.js
|
54
|
+
- app/assets/javascripts/pagelet_rails/jquery.ajaxprogress.js
|
55
|
+
- app/assets/javascripts/views/modal_dialog.jst.ejs
|
56
|
+
- app/assets/javascripts/views/modal_dialog_iframe.jst.ejs
|
57
|
+
- app/assets/javascripts/views/pagelet_load_failed.jst.ejs
|
58
|
+
- app/assets/javascripts/views/pagelet_loading_overlay.jst.ejs
|
59
|
+
- app/controllers/pagelet_controller.rb
|
60
|
+
- app/controllers/pagelet_proxy_controller.rb
|
61
|
+
- app/helpers/pagelets_helper.rb
|
62
|
+
- app/views/layouts/pagelet_rails/container.html.slim
|
63
|
+
- app/views/layouts/pagelet_rails/inner.slim
|
64
|
+
- app/views/layouts/pagelet_rails/loading_placeholder.slim
|
65
|
+
- config/routes.rb
|
66
|
+
- lib/action_controller/action_caching.rb
|
67
|
+
- lib/action_controller/caching/actions.rb
|
68
|
+
- lib/pagelet_rails.rb
|
69
|
+
- lib/pagelet_rails/concerns/cache.rb
|
70
|
+
- lib/pagelet_rails/concerns/controller.rb
|
71
|
+
- lib/pagelet_rails/concerns/options.rb
|
72
|
+
- lib/pagelet_rails/concerns/placeholder.rb
|
73
|
+
- lib/pagelet_rails/concerns/response_wrapper.rb
|
74
|
+
- lib/pagelet_rails/concerns/routes.rb
|
75
|
+
- lib/pagelet_rails/encryptor.rb
|
76
|
+
- lib/pagelet_rails/engine.rb
|
77
|
+
- lib/pagelet_rails/router.rb
|
78
|
+
- lib/pagelet_rails/version.rb
|
79
|
+
- lib/tasks/pagelet_rails_tasks.rake
|
80
|
+
homepage: https://github.com/antulik/pagelet_rails
|
81
|
+
licenses:
|
82
|
+
- MIT
|
83
|
+
metadata: {}
|
84
|
+
post_install_message:
|
85
|
+
rdoc_options: []
|
86
|
+
require_paths:
|
87
|
+
- lib
|
88
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
requirements: []
|
99
|
+
rubyforge_project:
|
100
|
+
rubygems_version: 2.5.1
|
101
|
+
signing_key:
|
102
|
+
specification_version: 4
|
103
|
+
summary: Improve perceived performance of your rails application with minimum effort
|
104
|
+
test_files: []
|