fragmentary 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/.gitignore +11 -0
- data/.rspec +3 -0
- data/.travis.yml +7 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +611 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/fragmentary.gemspec +31 -0
- data/lib/fragmentary.rb +11 -0
- data/lib/fragmentary/dispatcher.rb +19 -0
- data/lib/fragmentary/fragment.rb +549 -0
- data/lib/fragmentary/fragments_helper.rb +62 -0
- data/lib/fragmentary/handler.rb +31 -0
- data/lib/fragmentary/publisher.rb +82 -0
- data/lib/fragmentary/request.rb +30 -0
- data/lib/fragmentary/request_queue.rb +139 -0
- data/lib/fragmentary/subscriber.rb +36 -0
- data/lib/fragmentary/subscription.rb +85 -0
- data/lib/fragmentary/user_session.rb +53 -0
- data/lib/fragmentary/version.rb +3 -0
- data/lib/fragmentary/widget.rb +56 -0
- data/lib/fragmentary/widget_parser.rb +46 -0
- metadata +158 -0
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'rails/console/app'
|
2
|
+
|
3
|
+
module Fragmentary
|
4
|
+
|
5
|
+
class UserSession
|
6
|
+
|
7
|
+
include Rails::ConsoleMethods
|
8
|
+
|
9
|
+
attr_reader :session, :user
|
10
|
+
|
11
|
+
def initialize(*user, &block)
|
12
|
+
# app is from Rails::ConsoleMethods. It returns an object ActionDispatch::Integration::Session.new(Rails.application)
|
13
|
+
# with some extensions. See https://github.com/rails/rails/blob/master/railties/lib/rails/console/app.rb
|
14
|
+
# The session object has instance methods get, post etc.
|
15
|
+
# See https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/testing/integration.rb
|
16
|
+
@session = app
|
17
|
+
sign_in if @user = get_user(*user)
|
18
|
+
instance_eval(&block) if block_given?
|
19
|
+
end
|
20
|
+
|
21
|
+
def method_missing(method, *args)
|
22
|
+
session.send(method, *args)
|
23
|
+
end
|
24
|
+
|
25
|
+
def sign_out
|
26
|
+
post '/users/sign_out', {:_method => 'delete', :authenticity_token => request.session[:_csrf_token]}
|
27
|
+
end
|
28
|
+
|
29
|
+
def sign_in
|
30
|
+
get "/users/sign_in" # necessary in order to get the csrf token
|
31
|
+
# NOTE: In Rails 5, params is changed to a named argument, i.e. :params => {...}. Will need to be changed.
|
32
|
+
post "/users/sign_in", {:user => {:email => user.email, :password => user.try(:password)},
|
33
|
+
:authenticity_token => request.session[:_csrf_token]}
|
34
|
+
if session.redirect?
|
35
|
+
follow_redirect!
|
36
|
+
else
|
37
|
+
raise "Sign in failed for user #{user.name} #{user.password}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
def get_user(*attrs)
|
43
|
+
return nil if attrs.nil?
|
44
|
+
if (user = attrs.shift).is_a? User and user.password
|
45
|
+
user
|
46
|
+
elsif user.is_a? String
|
47
|
+
User.test_user(user, :admin => attrs.shift.try(:delete, :admin))
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Fragmentary
|
2
|
+
|
3
|
+
class Widget
|
4
|
+
attr_reader :template, :key, :match
|
5
|
+
|
6
|
+
def self.inherited subclass
|
7
|
+
super if defined? super
|
8
|
+
@subclasses ||= []
|
9
|
+
@subclasses << subclass
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.subclasses
|
13
|
+
@subclasses ||= []
|
14
|
+
@subclasses.inject([]) do |list, subclass|
|
15
|
+
list.push(subclass, *subclass.subclasses)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(template, key)
|
20
|
+
@template = template
|
21
|
+
@key = key
|
22
|
+
@match = key.match(pattern)
|
23
|
+
end
|
24
|
+
|
25
|
+
def pattern
|
26
|
+
Regexp.new('^$')
|
27
|
+
end
|
28
|
+
|
29
|
+
def _content
|
30
|
+
match ? content : nil
|
31
|
+
end
|
32
|
+
|
33
|
+
def content
|
34
|
+
"Undefined Widget"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
class UserWidget < Widget
|
40
|
+
attr_reader :current_user
|
41
|
+
|
42
|
+
def initialize(template, key)
|
43
|
+
super
|
44
|
+
@current_user = template.respond_to?(:current_user) ? template.current_user : nil
|
45
|
+
end
|
46
|
+
|
47
|
+
def _content
|
48
|
+
match ? user_content : nil
|
49
|
+
end
|
50
|
+
|
51
|
+
def user_content
|
52
|
+
current_user ? content : ""
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Fragmentary
|
2
|
+
|
3
|
+
class WidgetParser
|
4
|
+
|
5
|
+
include ActionView::Helpers::JavaScriptHelper
|
6
|
+
|
7
|
+
attr_reader :template, :current_user, :widget_container
|
8
|
+
|
9
|
+
def initialize(template)
|
10
|
+
@template = template
|
11
|
+
@widget_container = {:'' => 'Empty widget specification detected'}
|
12
|
+
end
|
13
|
+
|
14
|
+
# This method returns a new OutputBuffer instance that can be used to overwrite the existing
|
15
|
+
# template's output_buffer with a copy that has its widget specifications expanded. It is
|
16
|
+
# usually called from cache_fragment to insert widgets into a cached root fragment. However
|
17
|
+
# when an ajax request inserts a non-root fragment into a page it can be invoked from
|
18
|
+
# CacheBuilder#cache_child if that method is called with the :insert_widgets option set to
|
19
|
+
# true. Alternatively if an ajax request inserts content containing a widget without a fragment
|
20
|
+
# context, i.e. in order to modify content *within* a fragment, a WidgetParser can be
|
21
|
+
# instantiated separately using erb at the end of the view template. This can be done either
|
22
|
+
# in an html template if the client is loading html by ajax (e.g. jQuery.load) or in a js(.coffee)
|
23
|
+
# script if the ajax request loads javascript.
|
24
|
+
def parse_buffer(options = {})
|
25
|
+
template.output_buffer.scan(/%{([^}]+)}/) do |spec|
|
26
|
+
widget_key = spec[0]; widget = nil
|
27
|
+
widget_container[widget_key.to_sym] = if Widget.subclasses.find{|klass| (widget = klass.new(template, widget_key)).match}
|
28
|
+
if options[:javascript] or options[:js]
|
29
|
+
escape_javascript(widget._content)
|
30
|
+
else
|
31
|
+
widget._content
|
32
|
+
end
|
33
|
+
else
|
34
|
+
"Oops! Widget not found."
|
35
|
+
end
|
36
|
+
end
|
37
|
+
# The gsub replaces instances of '%' that aren't part of widget specifications with '%%', preventing
|
38
|
+
# those characters from making the buffer an invalid format specification. The substitution operation
|
39
|
+
# restores them to single characters. The new OutputBuffer is needed because gsub returns a string.
|
40
|
+
# (Although gsub! would return an OutputBuffer if a substitution occurs, it returns nil otherwise,
|
41
|
+
# so isn't suitable here.)
|
42
|
+
ActionView::OutputBuffer.new(template.output_buffer.gsub(/%(?!{)/,'%%') % widget_container)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
metadata
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fragmentary
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mark Thomson
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-12-07 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: 4.0.0
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '5'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 4.0.0
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '5'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: delayed_job_active_record
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '4.1'
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '4.1'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: wisper-activerecord
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '1.0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '1.0'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: bundler
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '1.17'
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '1.17'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: rake
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '10.0'
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '10.0'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: rspec
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "~>"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '3.0'
|
96
|
+
type: :development
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - "~>"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '3.0'
|
103
|
+
description: Fragment caching for Rails with arbitrarily complex data dependencies
|
104
|
+
email:
|
105
|
+
- mark.thomson@persuasivethinking.com
|
106
|
+
executables: []
|
107
|
+
extensions: []
|
108
|
+
extra_rdoc_files: []
|
109
|
+
files:
|
110
|
+
- ".gitignore"
|
111
|
+
- ".rspec"
|
112
|
+
- ".travis.yml"
|
113
|
+
- Gemfile
|
114
|
+
- LICENSE.txt
|
115
|
+
- README.md
|
116
|
+
- Rakefile
|
117
|
+
- bin/console
|
118
|
+
- bin/setup
|
119
|
+
- fragmentary.gemspec
|
120
|
+
- lib/fragmentary.rb
|
121
|
+
- lib/fragmentary/dispatcher.rb
|
122
|
+
- lib/fragmentary/fragment.rb
|
123
|
+
- lib/fragmentary/fragments_helper.rb
|
124
|
+
- lib/fragmentary/handler.rb
|
125
|
+
- lib/fragmentary/publisher.rb
|
126
|
+
- lib/fragmentary/request.rb
|
127
|
+
- lib/fragmentary/request_queue.rb
|
128
|
+
- lib/fragmentary/subscriber.rb
|
129
|
+
- lib/fragmentary/subscription.rb
|
130
|
+
- lib/fragmentary/user_session.rb
|
131
|
+
- lib/fragmentary/version.rb
|
132
|
+
- lib/fragmentary/widget.rb
|
133
|
+
- lib/fragmentary/widget_parser.rb
|
134
|
+
homepage: https://github.com/MarkMT/fragmentary
|
135
|
+
licenses:
|
136
|
+
- MIT
|
137
|
+
metadata: {}
|
138
|
+
post_install_message:
|
139
|
+
rdoc_options: []
|
140
|
+
require_paths:
|
141
|
+
- lib
|
142
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
144
|
+
- - ">="
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: '0'
|
147
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - ">="
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '0'
|
152
|
+
requirements: []
|
153
|
+
rubyforge_project:
|
154
|
+
rubygems_version: 2.4.8
|
155
|
+
signing_key:
|
156
|
+
specification_version: 4
|
157
|
+
summary: Fragment modeling and caching for Rails
|
158
|
+
test_files: []
|