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,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,4 @@
1
+ module PageletRails
2
+ class Engine < ::Rails::Engine
3
+ end
4
+ 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,3 @@
1
+ module PageletRails
2
+ VERSION = '0.1.0'
3
+ 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
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :pagelet_rails do
3
+ # # Task goes here
4
+ # 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: []