props_template 0.21.0 → 0.22.1
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 +4 -4
- data/README.md +12 -12
- data/lib/props_template/base_with_extensions.rb +4 -8
- data/lib/props_template/extension_manager.rb +0 -5
- data/lib/props_template/extensions/partial_renderer.rb +46 -112
- data/lib/props_template/searcher.rb +0 -2
- data/lib/props_template/version.rb +1 -1
- data/lib/props_template.rb +9 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 18da6492527680c8726d4b774e411bda247f6e49d2a992c2d9b9fa1bd9555633
|
4
|
+
data.tar.gz: 391d5b171c9816593f74a681c581075cd426a8eb29827a6a522dc21908e82875
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8f3d71ec0398e27c05ca134e5dedb0fb96d6c6d5e725b271863bacf9fc907bca4a5b723416305c3051a38d1ec6ee692a9896d1698cf8278191b9804d4e8918c9
|
7
|
+
data.tar.gz: f691118fb075e94b68462652d296ac0e7b2d294a44fe5abc088b3bdac8ef0aa9c4233a84e57a22c5274e10b3ef7f5e8b98d850db4d7cf4054580a96d152bb0a8
|
data/README.md
CHANGED
@@ -257,8 +257,8 @@ may still need to implement `member_by`.
|
|
257
257
|
### json.deferred!
|
258
258
|
Returns all deferred nodes used by the [deferment](#deferment) option.
|
259
259
|
|
260
|
-
**Note** This is a [
|
261
|
-
`application.json.props` when first running `rails
|
260
|
+
**Note** This is a [SuperglueJS][1] specific functionality and is used in
|
261
|
+
`application.json.props` when first running `rails superglue:install:web`
|
262
262
|
|
263
263
|
|
264
264
|
```ruby
|
@@ -267,7 +267,7 @@ json.deferred json.deferred!
|
|
267
267
|
# => [{url: '/some_url?props_at=outer.inner', path: 'outer.inner', type: 'auto'}]
|
268
268
|
```
|
269
269
|
|
270
|
-
This method provides metadata about deferred nodes to the frontend ([
|
270
|
+
This method provides metadata about deferred nodes to the frontend ([SuperglueJS][1])
|
271
271
|
to fetch missing data in a second round trip.
|
272
272
|
|
273
273
|
### json.fragments!
|
@@ -276,8 +276,8 @@ option.
|
|
276
276
|
|
277
277
|
```ruby json.fragments json.fragments! ```
|
278
278
|
|
279
|
-
**Note** This is a [
|
280
|
-
`application.json.props` when first running `rails
|
279
|
+
**Note** This is a [SuperglueJS][1] specific functionality and is used in
|
280
|
+
`application.json.props` when first running `rails superglue:install:web`
|
281
281
|
|
282
282
|
## Options
|
283
283
|
Options Functionality such as Partials, Deferements, and Caching can only be
|
@@ -311,7 +311,7 @@ end
|
|
311
311
|
```
|
312
312
|
|
313
313
|
### Partial Fragments
|
314
|
-
**Note** This is a [
|
314
|
+
**Note** This is a [SuperglueJS][1] specific functionality.
|
315
315
|
|
316
316
|
A fragment identifies a partial output across multiple pages. It can be used to
|
317
317
|
update cross cutting concerns like a header bar.
|
@@ -393,7 +393,7 @@ tabbed content that does not load until you click the tab.
|
|
393
393
|
When your client receives the payload, you may issue a second request to the
|
394
394
|
same endpoint to fetch any missing nodes. See [traversing nodes](#traversing)
|
395
395
|
|
396
|
-
There is also an `defer: :auto` option that you can use with [
|
396
|
+
There is also an `defer: :auto` option that you can use with [SuperglueJS][1]. [SuperglueJS][1]
|
397
397
|
will use the metadata from `json.deferred!` to issue a `remote` dispatch to fetch
|
398
398
|
the missing node and immutably graft it at the appropriate keypath in your Redux
|
399
399
|
store.
|
@@ -417,7 +417,7 @@ end
|
|
417
417
|
|
418
418
|
A auto option is available:
|
419
419
|
|
420
|
-
**Note** This is a [
|
420
|
+
**Note** This is a [SuperglueJS][1] specific functionality.
|
421
421
|
|
422
422
|
```ruby
|
423
423
|
json.dashboard(defer: :auto) do
|
@@ -436,14 +436,14 @@ json.defers json.deferred!
|
|
436
436
|
The default behavior for deferements is to use the index of the collection to
|
437
437
|
identify an element.
|
438
438
|
|
439
|
-
**Note** If you are using this library with [
|
439
|
+
**Note** If you are using this library with [SuperglueJS][1], the `:auto` options will
|
440
440
|
generate `?props_at=a.b.c.0.title` for `json.deferred!`.
|
441
441
|
|
442
442
|
If you wish to use an attribute to identify the element. You must:
|
443
443
|
|
444
444
|
1. Use the `:key` option on `json.array!`. This key refers to an attribute on
|
445
445
|
your collection item, and is used for `defer: :auto` to generate a keypath for
|
446
|
-
[
|
446
|
+
[SuperglueJS][1]. If you are NOT using SuperglueJS, you do not need to do this.
|
447
447
|
|
448
448
|
2. Implement `member_at`, on the [collection](#jsonarray). This will be called
|
449
449
|
by PropsTemplate to when [searching nodes](#traversing)
|
@@ -469,7 +469,7 @@ json.posts
|
|
469
469
|
end
|
470
470
|
```
|
471
471
|
|
472
|
-
If you are using [
|
472
|
+
If you are using [SuperglueJS][1], SuperglueJS will, it will automatically kick off
|
473
473
|
`remote(?props_at=posts.some_id=1.contact)` and `remote(?props_at=posts.some_id=2.contact)`.
|
474
474
|
|
475
475
|
## Traversing
|
@@ -596,4 +596,4 @@ See the [CONTRIBUTING] document. Thank you, [contributors]!
|
|
596
596
|
Thanks to [turbostreamer](https://github.com/malomalo/turbostreamer) for the
|
597
597
|
inspiration.
|
598
598
|
|
599
|
-
[1]: https://github.com/thoughtbot/
|
599
|
+
[1]: https://github.com/thoughtbot/superglue
|
@@ -1,11 +1,3 @@
|
|
1
|
-
require 'props_template/base'
|
2
|
-
require 'props_template/extensions/partial_renderer'
|
3
|
-
require 'props_template/extensions/cache'
|
4
|
-
require 'props_template/extensions/deferment'
|
5
|
-
require 'props_template/extension_manager'
|
6
|
-
require 'active_support/core_ext/string/output_safety'
|
7
|
-
require 'active_support/core_ext/array'
|
8
|
-
|
9
1
|
module Props
|
10
2
|
class BaseWithExtensions < Base
|
11
3
|
attr_reader :builder, :context, :fragments, :traveled_path, :deferred, :stream
|
@@ -28,6 +20,10 @@ module Props
|
|
28
20
|
@em.fragments
|
29
21
|
end
|
30
22
|
|
23
|
+
def traveled_path!
|
24
|
+
@traveled_path.join(".")
|
25
|
+
end
|
26
|
+
|
31
27
|
def set_block_content!(options = {})
|
32
28
|
return super if !@em.has_extensions(options)
|
33
29
|
|
@@ -1,8 +1,3 @@
|
|
1
|
-
require 'props_template/extensions/partial_renderer'
|
2
|
-
require 'props_template/extensions/cache'
|
3
|
-
require 'props_template/extensions/deferment'
|
4
|
-
require 'props_template/extensions/fragment'
|
5
|
-
|
6
1
|
module Props
|
7
2
|
class ExtensionManager
|
8
3
|
attr_reader :base, :builder, :context
|
@@ -17,6 +17,12 @@ module Props
|
|
17
17
|
|
18
18
|
class Partialer
|
19
19
|
INVALID_PARTIAL_MESSAGE = "The partial name must be a string, but received (%s)."
|
20
|
+
OPTION_AS_ERROR_MESSAGE = "The value (%s) of the option `as` is not a valid Ruby identifier; " \
|
21
|
+
"make sure it starts with lowercase letter, " \
|
22
|
+
"and is followed by any combination of letters, numbers and underscores."
|
23
|
+
IDENTIFIER_ERROR_MESSAGE = "The partial name (%s) is not a valid Ruby identifier; " \
|
24
|
+
"make sure your partial name starts with underscore."
|
25
|
+
|
20
26
|
|
21
27
|
def initialize(base, context, builder)
|
22
28
|
@context = context
|
@@ -24,30 +30,28 @@ module Props
|
|
24
30
|
@base = base
|
25
31
|
end
|
26
32
|
|
27
|
-
def extract_details(options)
|
28
|
-
|
33
|
+
def extract_details(options)
|
34
|
+
registered_details.each_with_object({}) do |key, details|
|
29
35
|
value = options[key]
|
30
36
|
|
31
37
|
details[key] = Array(value) if value
|
32
38
|
end
|
33
39
|
end
|
34
40
|
|
41
|
+
def registered_details
|
42
|
+
if ActionView.version.to_s >= "7"
|
43
|
+
ActionView::LookupContext.registered_details
|
44
|
+
else
|
45
|
+
@context.lookup_context.registered_details
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
35
49
|
def find_and_add_template(all_options)
|
36
50
|
first_opts = all_options[0]
|
37
51
|
|
38
52
|
if first_opts[:partial]
|
39
53
|
partial_opts = block_opts_to_render_opts(@builder, first_opts)
|
40
|
-
|
41
|
-
partial_opts.delete(:handlers)
|
42
|
-
partial = partial_opts[:partial]
|
43
|
-
|
44
|
-
if !(String === partial)
|
45
|
-
raise ArgumentError.new(INVALID_PARTIAL_MESSAGE % (partial.inspect))
|
46
|
-
end
|
47
|
-
|
48
|
-
template_keys = retrieve_template_keys(partial_opts)
|
49
|
-
details = extract_details(partial_opts)
|
50
|
-
template = find_template(partial, template_keys, details)
|
54
|
+
template = find_template(partial_opts)
|
51
55
|
|
52
56
|
all_options.map do |opts|
|
53
57
|
opts[:_template] = template
|
@@ -58,9 +62,13 @@ module Props
|
|
58
62
|
end
|
59
63
|
end
|
60
64
|
|
61
|
-
def find_template(
|
62
|
-
|
63
|
-
|
65
|
+
def find_template(partial_opts)
|
66
|
+
partial = partial_opts[:partial]
|
67
|
+
template_keys = retrieve_template_keys(partial_opts)
|
68
|
+
details = extract_details(partial_opts)
|
69
|
+
|
70
|
+
prefixes = partial.include?(?/) ? [] : @context.lookup_context.prefixes
|
71
|
+
@context.lookup_context.find_template(partial, prefixes, true, template_keys, details)
|
64
72
|
end
|
65
73
|
|
66
74
|
def retrieve_template_keys(options)
|
@@ -75,24 +83,24 @@ module Props
|
|
75
83
|
pass_opts[:locals] ||= {}
|
76
84
|
pass_opts[:locals][:json] = @builder
|
77
85
|
pass_opts[:partial] = partial
|
86
|
+
pass_opts[:formats] = [:json]
|
87
|
+
pass_opts.delete(:handlers)
|
78
88
|
|
79
|
-
|
80
|
-
|
89
|
+
if !(String === partial)
|
90
|
+
raise ArgumentError.new(INVALID_PARTIAL_MESSAGE % (partial.inspect))
|
91
|
+
end
|
81
92
|
|
82
|
-
|
83
|
-
PartialRenderer.refine_options(options, item)
|
93
|
+
pass_opts
|
84
94
|
end
|
85
95
|
|
86
96
|
def handle(options)
|
87
|
-
|
88
|
-
|
89
|
-
template = options[:_template] || renderer.template
|
97
|
+
partial_opts = block_opts_to_render_opts(@builder, options)
|
98
|
+
template = options[:_template] || find_template(partial_opts)
|
90
99
|
|
91
|
-
|
100
|
+
render_partial(template, @context, partial_opts)
|
92
101
|
end
|
93
102
|
|
94
|
-
def
|
95
|
-
view = @context
|
103
|
+
def render_partial(template, view, options)
|
96
104
|
instrument(:partial, identifier: template.identifier) do |payload|
|
97
105
|
locals = options[:locals]
|
98
106
|
content = template.render(view, locals)
|
@@ -101,33 +109,32 @@ module Props
|
|
101
109
|
build_rendered_template(content, template)
|
102
110
|
end
|
103
111
|
end
|
104
|
-
end
|
105
|
-
|
106
|
-
class PartialRenderer
|
107
|
-
OPTION_AS_ERROR_MESSAGE = "The value (%s) of the option `as` is not a valid Ruby identifier; " \
|
108
|
-
"make sure it starts with lowercase letter, " \
|
109
|
-
"and is followed by any combination of letters, numbers and underscores."
|
110
|
-
IDENTIFIER_ERROR_MESSAGE = "The partial name (%s) is not a valid Ruby identifier; " \
|
111
|
-
"make sure your partial name starts with underscore."
|
112
112
|
|
113
|
-
|
113
|
+
def build_rendered_template(content, template, layout = nil)
|
114
|
+
RenderedTemplate.new content, layout, template
|
115
|
+
end
|
114
116
|
|
117
|
+
def instrument(name, **options) # :doc:
|
118
|
+
ActiveSupport::Notifications.instrument("render_#{name}.action_view", options) do |payload|
|
119
|
+
yield payload
|
120
|
+
end
|
121
|
+
end
|
115
122
|
|
116
|
-
def
|
123
|
+
def raise_invalid_option_as(as)
|
117
124
|
raise ArgumentError.new(OPTION_AS_ERROR_MESSAGE % (as))
|
118
125
|
end
|
119
126
|
|
120
|
-
def
|
127
|
+
def raise_invalid_identifier(path)
|
121
128
|
raise ArgumentError.new(IDENTIFIER_ERROR_MESSAGE % (path))
|
122
129
|
end
|
123
130
|
|
124
|
-
def
|
131
|
+
def retrieve_variable(path)
|
125
132
|
base = path[-1] == "/" ? "" : File.basename(path)
|
126
133
|
raise_invalid_identifier(path) unless base =~ /\A_?(.*?)(?:\.\w+)*\z/
|
127
134
|
$1.to_sym
|
128
135
|
end
|
129
136
|
|
130
|
-
def
|
137
|
+
def refine_options(options, item = nil)
|
131
138
|
return options if !options[:partial]
|
132
139
|
|
133
140
|
partial, rest = [*options[:partial]]
|
@@ -156,78 +163,5 @@ module Props
|
|
156
163
|
|
157
164
|
pass_opts
|
158
165
|
end
|
159
|
-
|
160
|
-
attr_reader :template
|
161
|
-
|
162
|
-
def initialize(context, options)
|
163
|
-
@context = context
|
164
|
-
@options = options.merge(formats: [:json])
|
165
|
-
@options.delete(:handlers)
|
166
|
-
@details = extract_details(@options)
|
167
|
-
|
168
|
-
partial = @options[:partial]
|
169
|
-
|
170
|
-
if !(String === partial)
|
171
|
-
raise_invalid_partial(partial.inspect)
|
172
|
-
end
|
173
|
-
|
174
|
-
@path = partial
|
175
|
-
|
176
|
-
template_keys = retrieve_template_keys(@options)
|
177
|
-
@template = find_template(@path, template_keys)
|
178
|
-
end
|
179
|
-
|
180
|
-
def render(template, options)
|
181
|
-
#remove this later
|
182
|
-
|
183
|
-
render_partial(template, @context, @options)
|
184
|
-
end
|
185
|
-
|
186
|
-
private
|
187
|
-
def extract_details(options) # :doc:
|
188
|
-
@context.lookup_context.registered_details.each_with_object({}) do |key, details|
|
189
|
-
value = options[key]
|
190
|
-
|
191
|
-
details[key] = Array(value) if value
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
def instrument(name, **options) # :doc:
|
196
|
-
ActiveSupport::Notifications.instrument("render_#{name}.action_view", options) do |payload|
|
197
|
-
yield payload
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
def render_partial(template, view, options)
|
202
|
-
template ||= @template
|
203
|
-
# @variable ||= template.variable
|
204
|
-
|
205
|
-
instrument(:partial, identifier: @template.identifier) do |payload|
|
206
|
-
locals = options[:locals]
|
207
|
-
content = template.render(view, locals)
|
208
|
-
|
209
|
-
payload[:cache_hit] = view.view_renderer.cache_hits[template.virtual_path]
|
210
|
-
build_rendered_template(content, template)
|
211
|
-
end
|
212
|
-
end
|
213
|
-
|
214
|
-
def build_rendered_template(content, template, layout = nil)
|
215
|
-
RenderedTemplate.new content, layout, template
|
216
|
-
end
|
217
|
-
|
218
|
-
def find_template(path, locals)
|
219
|
-
prefixes = path.include?(?/) ? [] : @context.lookup_context.prefixes
|
220
|
-
@context.lookup_context.find_template(path, prefixes, true, locals, @details)
|
221
|
-
end
|
222
|
-
|
223
|
-
def retrieve_template_keys(options)
|
224
|
-
template_keys = options[:locals].keys
|
225
|
-
template_keys << options[:as] if options[:as]
|
226
|
-
template_keys
|
227
|
-
end
|
228
|
-
|
229
|
-
def raise_invalid_partial(path)
|
230
|
-
raise ArgumentError.new(INVALID_PARTIAL_MESSAGE % (path))
|
231
|
-
end
|
232
166
|
end
|
233
167
|
end
|
data/lib/props_template.rb
CHANGED
@@ -1,4 +1,12 @@
|
|
1
|
+
require 'props_template/base'
|
2
|
+
require 'props_template/extensions/partial_renderer'
|
3
|
+
require 'props_template/extensions/cache'
|
4
|
+
require 'props_template/extensions/deferment'
|
5
|
+
require 'props_template/extensions/fragment'
|
1
6
|
require 'props_template/base_with_extensions'
|
7
|
+
require 'props_template/extension_manager'
|
8
|
+
require 'active_support/core_ext/string/output_safety'
|
9
|
+
require 'active_support/core_ext/array'
|
2
10
|
require 'props_template/searcher'
|
3
11
|
require 'props_template/handler'
|
4
12
|
require 'props_template/version'
|
@@ -17,6 +25,7 @@ module Props
|
|
17
25
|
:deferred!,
|
18
26
|
:fragments!,
|
19
27
|
:set_block_content!,
|
28
|
+
:traveled_path!,
|
20
29
|
to: :builder!
|
21
30
|
|
22
31
|
def initialize(context = nil, options = {})
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: props_template
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.22.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Johny Ho
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-05-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|