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