props_template 0.17.1 → 0.20.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 +4 -4
- data/README.md +193 -98
- data/lib/props_template.rb +1 -0
- data/lib/props_template/version.rb +3 -0
- metadata +11 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4cf7de015844e77efdf93e02272159080835cad2e0f6022e610690727a05cfb5
|
|
4
|
+
data.tar.gz: 350d1a534d30c625b7adbe3c95d6ac33c2a831205c970c404bb2c9eeb22dfd69
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 533ff82a0dac43e211d9a5800b71ef9ec59a4e8d34d16214a3799ea7398e9746a1d0b823db55bfd4b272ea9a48a9e685a3f49fc437f8b7a7aa1ed49ef2d531c8
|
|
7
|
+
data.tar.gz: 0fc9fc3e0b1d898c1870c286d14dcd59e8a6679d428c026dcf2c6107ef8e281f40d0e08838f625e1a39b321199510920fe2e3a1b9ff20a08990106220fffc949
|
data/README.md
CHANGED
|
@@ -1,15 +1,29 @@
|
|
|
1
1
|
# PropsTemplate
|
|
2
2
|
|
|
3
|
-
PropsTemplate is a direct-to-Oj, JBuilder-like DSL for building JSON. It has
|
|
3
|
+
PropsTemplate is a direct-to-Oj, JBuilder-like DSL for building JSON. It has
|
|
4
|
+
support for Russian-Doll caching, layouts, and can be queried by giving the
|
|
5
|
+
root a key path.
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
[](https://circleci.com/gh/thoughtbot/props_template)
|
|
6
9
|
|
|
7
|
-
|
|
10
|
+
It's fast.
|
|
8
11
|
|
|
9
|
-
PropsTemplate
|
|
12
|
+
PropsTemplate bypasses the steps of hash building and serializing
|
|
13
|
+
that other libraries perform by using Oj's `StringWriter` in `rails` mode.
|
|
10
14
|
|
|
15
|
+

|
|
11
16
|
|
|
12
|
-
|
|
17
|
+
Caching is fast too.
|
|
18
|
+
|
|
19
|
+
While other libraries spend time unmarshaling,
|
|
20
|
+
merging hashes, and serializing to JSON; PropsTemplate simply takes
|
|
21
|
+
the cached string and uses Oj's [push_json](http://www.ohler.com/oj/doc/Oj/StringWriter.html#push_json-instance_method).
|
|
22
|
+
|
|
23
|
+
## Example:
|
|
24
|
+
|
|
25
|
+
PropsTemplate is very similar to JBuilder, and selectively retains some
|
|
26
|
+
conveniences and magic.
|
|
13
27
|
|
|
14
28
|
```ruby
|
|
15
29
|
json.flash flash.to_h
|
|
@@ -47,13 +61,11 @@ json.posts do
|
|
|
47
61
|
json.total @posts.count
|
|
48
62
|
end
|
|
49
63
|
|
|
50
|
-
|
|
51
64
|
json.footer partial: 'shared/footer' do
|
|
52
65
|
end
|
|
53
66
|
```
|
|
54
67
|
|
|
55
68
|
## Installation
|
|
56
|
-
If you plan to use PropsTemplate alone just add it to your Gemfile.
|
|
57
69
|
|
|
58
70
|
```
|
|
59
71
|
gem 'props_template'
|
|
@@ -63,18 +75,19 @@ and run `bundle`
|
|
|
63
75
|
|
|
64
76
|
## API
|
|
65
77
|
|
|
66
|
-
### json.set! or json
|
|
67
|
-
|
|
78
|
+
### json.set! or json.\<your key here\>
|
|
79
|
+
|
|
80
|
+
Defines the attribute or structure. All keys are automatically camelized lower.
|
|
68
81
|
|
|
69
82
|
```ruby
|
|
70
|
-
json.set! :author_details, {
|
|
83
|
+
json.set! :author_details, {...options} do
|
|
71
84
|
json.set! :first_name, 'David'
|
|
72
85
|
end
|
|
73
86
|
|
|
74
87
|
or
|
|
75
88
|
|
|
76
|
-
json.author_details, {
|
|
77
|
-
json.first_name
|
|
89
|
+
json.author_details, {...options} do
|
|
90
|
+
json.first_name 'David'
|
|
78
91
|
end
|
|
79
92
|
|
|
80
93
|
|
|
@@ -89,6 +102,7 @@ The inline form defines key and value
|
|
|
89
102
|
| value | A value |
|
|
90
103
|
|
|
91
104
|
```ruby
|
|
105
|
+
|
|
92
106
|
json.set! :first_name, 'David'
|
|
93
107
|
|
|
94
108
|
or
|
|
@@ -108,39 +122,36 @@ The block form defines key and structure
|
|
|
108
122
|
|
|
109
123
|
```ruby
|
|
110
124
|
json.set! :details do
|
|
111
|
-
|
|
125
|
+
...
|
|
112
126
|
end
|
|
113
127
|
|
|
114
128
|
or
|
|
115
129
|
|
|
116
130
|
json.details do
|
|
117
|
-
|
|
131
|
+
...
|
|
118
132
|
end
|
|
119
133
|
```
|
|
120
134
|
|
|
121
135
|
The difference between the block form and inline form is
|
|
122
|
-
1. The block form is an internal node.
|
|
123
|
-
|
|
136
|
+
1. The block form is an internal node. Functionality such as Partials,
|
|
137
|
+
Deferment and other [options](#options) are only available on the
|
|
138
|
+
block form.
|
|
139
|
+
2. The inline form is considered a leaf node, and you can only [search](#traversing)
|
|
140
|
+
for internal nodes.
|
|
124
141
|
|
|
125
142
|
### json.array!
|
|
126
143
|
Generates an array of json objects.
|
|
127
144
|
|
|
128
145
|
```ruby
|
|
129
|
-
collection = [
|
|
130
|
-
{name: 'john'},
|
|
131
|
-
{name: 'jim'}
|
|
132
|
-
]
|
|
146
|
+
collection = [ {name: 'john'}, {name: 'jim'} ]
|
|
133
147
|
|
|
134
148
|
json.details do
|
|
135
|
-
json.array! collection, {
|
|
149
|
+
json.array! collection, {...options} do |person|
|
|
136
150
|
json.first_name person[:name]
|
|
137
151
|
end
|
|
138
152
|
end
|
|
139
153
|
|
|
140
|
-
# => {"details": [
|
|
141
|
-
{"firstName": 'john'},
|
|
142
|
-
{"firstName": 'jim'}
|
|
143
|
-
]}
|
|
154
|
+
# => {"details": [{"firstName": 'john'}, {"firstName": 'jim'} ]}
|
|
144
155
|
```
|
|
145
156
|
|
|
146
157
|
| Parameter | Notes |
|
|
@@ -148,7 +159,8 @@ end
|
|
|
148
159
|
| collection | A collection that responds to `member_at` and `member_by` |
|
|
149
160
|
| options | Additional [options](#options)|
|
|
150
161
|
|
|
151
|
-
To support [traversing nodes](
|
|
162
|
+
To support [traversing nodes](#traversing), any list passed
|
|
163
|
+
to `array!` MUST implement `member_at(index)` and `member_by(attr, value)`.
|
|
152
164
|
|
|
153
165
|
For example, if you were using a delegate:
|
|
154
166
|
|
|
@@ -169,7 +181,10 @@ end
|
|
|
169
181
|
Then in your template:
|
|
170
182
|
|
|
171
183
|
```ruby
|
|
172
|
-
data = ObjectCollection.new([
|
|
184
|
+
data = ObjectCollection.new([
|
|
185
|
+
{id: 1, name: 'foo'},
|
|
186
|
+
{id: 2, name: 'bar'}
|
|
187
|
+
])
|
|
173
188
|
|
|
174
189
|
json.array! data do
|
|
175
190
|
...
|
|
@@ -200,11 +215,15 @@ end
|
|
|
200
215
|
|
|
201
216
|
#### **Array core extension**
|
|
202
217
|
|
|
203
|
-
For convenience, PropsTemplate includes a core\_ext that adds these methods to
|
|
218
|
+
For convenience, PropsTemplate includes a core\_ext that adds these methods to
|
|
219
|
+
`Array`. For example:
|
|
204
220
|
|
|
205
221
|
```ruby
|
|
206
222
|
require 'props_template/core_ext'
|
|
207
|
-
data = [
|
|
223
|
+
data = [
|
|
224
|
+
{id: 1, name: 'foo'},
|
|
225
|
+
{id: 2, name: 'bar'}
|
|
226
|
+
]
|
|
208
227
|
|
|
209
228
|
json.posts
|
|
210
229
|
json.array! data do
|
|
@@ -213,28 +232,39 @@ json.posts
|
|
|
213
232
|
end
|
|
214
233
|
```
|
|
215
234
|
|
|
216
|
-
PropsTemplate does not know what the elements are in your collection. The
|
|
235
|
+
PropsTemplate does not know what the elements are in your collection. The
|
|
236
|
+
example above will be fine for [traversing](#traversing)
|
|
237
|
+
by index, but will raise a `NotImplementedError` if you query by attribute. You
|
|
238
|
+
may still need to implement `member_by`.
|
|
217
239
|
|
|
218
240
|
### json.deferred!
|
|
219
|
-
Returns all deferred nodes used by the [
|
|
241
|
+
Returns all deferred nodes used by the [deferment](#deferment) option.
|
|
242
|
+
|
|
243
|
+
**Note** This is a [BreezyJS][1] specific functionality and is used in
|
|
244
|
+
`application.json.props` when first running `rails breezy:install:web`
|
|
245
|
+
|
|
220
246
|
|
|
221
247
|
```ruby
|
|
222
248
|
json.deferred json.deferred!
|
|
249
|
+
|
|
250
|
+
# => [{url: '/some_url?bzq=outer.inner', path: 'outer.inner', type: 'auto'}]
|
|
223
251
|
```
|
|
224
252
|
|
|
225
|
-
This method
|
|
253
|
+
This method provides metadata about deferred nodes to the frontend ([BreezyJS][1])
|
|
254
|
+
to fetch missing data in a second round trip.
|
|
226
255
|
|
|
227
256
|
### json.fragments!
|
|
228
|
-
Returns all fragment nodes used by the [partial fragments](#partial-fragments)
|
|
257
|
+
Returns all fragment nodes used by the [partial fragments](#partial-fragments)
|
|
258
|
+
option.
|
|
229
259
|
|
|
230
|
-
```ruby
|
|
231
|
-
json.fragments json.fragments!
|
|
232
|
-
```
|
|
260
|
+
```ruby json.fragments json.fragments! ```
|
|
233
261
|
|
|
234
|
-
This
|
|
262
|
+
**Note** This is a [BreezyJS][1] specific functionality and is used in
|
|
263
|
+
`application.json.props` when first running `rails breezy:install:web`
|
|
235
264
|
|
|
236
265
|
## Options
|
|
237
|
-
Functionality such as Partials, Deferements, and Caching can only be
|
|
266
|
+
Options Functionality such as Partials, Deferements, and Caching can only be
|
|
267
|
+
set on a block. It is normal to see empty blocks.
|
|
238
268
|
|
|
239
269
|
```ruby
|
|
240
270
|
json.post(partial: 'blog_post') do
|
|
@@ -243,7 +273,9 @@ end
|
|
|
243
273
|
|
|
244
274
|
### Partials
|
|
245
275
|
|
|
246
|
-
Partials are supported. The following will render the file
|
|
276
|
+
Partials are supported. The following will render the file
|
|
277
|
+
`views/posts/_blog_posts.json.props`, and set a local variable `foo` assigned
|
|
278
|
+
with @post, which you can use inside the partial.
|
|
247
279
|
|
|
248
280
|
```ruby
|
|
249
281
|
json.one_post partial: ["posts/blog_post", locals: {post: @post}] do
|
|
@@ -253,7 +285,8 @@ end
|
|
|
253
285
|
Usage with arrays:
|
|
254
286
|
|
|
255
287
|
```ruby
|
|
256
|
-
#
|
|
288
|
+
# The `as:` option is supported when using `array!`
|
|
289
|
+
|
|
257
290
|
json.posts do
|
|
258
291
|
json.array! @posts, partial: ["posts/blog_post", locals: {foo: 'bar'}, as: 'post'] do
|
|
259
292
|
end
|
|
@@ -261,14 +294,14 @@ end
|
|
|
261
294
|
```
|
|
262
295
|
|
|
263
296
|
### Partial Fragments
|
|
297
|
+
**Note** This is a [BreezyJS][1] specific functionality.
|
|
264
298
|
|
|
265
|
-
A fragment
|
|
266
|
-
|
|
267
|
-
You would need use partials and add the option `fragment: true`.
|
|
299
|
+
A fragment identifies a partial output across multiple pages. It can be used to
|
|
300
|
+
update cross cutting concerns like a header bar.
|
|
268
301
|
|
|
269
302
|
```ruby
|
|
270
303
|
# index.json.props
|
|
271
|
-
json.header partial: ["profile", fragment:
|
|
304
|
+
json.header partial: ["profile", fragment: "header"] do
|
|
272
305
|
end
|
|
273
306
|
|
|
274
307
|
# _profile.json.props
|
|
@@ -282,21 +315,16 @@ end
|
|
|
282
315
|
When using fragments with Arrays, the argument **MUST** be a lamda:
|
|
283
316
|
|
|
284
317
|
```ruby
|
|
285
|
-
require 'props_template/core_ext'
|
|
286
|
-
|
|
287
|
-
json.array! ['foo', 'bar'], partial: ["footer", fragment: ->(x){ x == 'foo'}]
|
|
288
|
-
```
|
|
289
|
-
|
|
290
|
-
PropsTemplate creates a name for the partial using a digest of your locals, partial name, and globalId (to_json as fallback if there is no globalId) on objects that you pass. You may override this behavior and use a custom identifier:
|
|
318
|
+
require 'props_template/core_ext'
|
|
291
319
|
|
|
292
|
-
|
|
293
|
-
# index.js.breezy
|
|
294
|
-
json.header partial: ["profile", fragment: 'me_header'] do
|
|
320
|
+
json.array! ['foo', 'bar'], partial: ["footer", fragment: ->(x){ x == 'foo'}] do
|
|
295
321
|
end
|
|
296
322
|
```
|
|
297
323
|
|
|
298
324
|
### Caching
|
|
299
|
-
Caching is supported on
|
|
325
|
+
Caching is supported on internal nodes only. This limitation is what makes it
|
|
326
|
+
possible to for props_template to forgo marshalling/unmarshalling and simply
|
|
327
|
+
use [push_json](http://www.ohler.com/oj/doc/Oj/StringWriter.html#push_json-instance_method).
|
|
300
328
|
|
|
301
329
|
Usage:
|
|
302
330
|
|
|
@@ -322,44 +350,60 @@ end
|
|
|
322
350
|
When used with arrays, PropsTemplate will use `Rails.cache.read_multi`.
|
|
323
351
|
|
|
324
352
|
```ruby
|
|
325
|
-
require 'props_template/core_ext'
|
|
353
|
+
require 'props_template/core_ext'
|
|
354
|
+
|
|
355
|
+
opts = { cache: ->(i){ ['a', i] } }
|
|
326
356
|
|
|
327
|
-
opts = {
|
|
328
|
-
cache: ->(i){ ['a', i] }
|
|
329
|
-
}
|
|
330
357
|
json.array! [4,5], opts do |x|
|
|
331
358
|
json.top "hello" + x.to_s
|
|
332
359
|
end
|
|
333
360
|
|
|
334
361
|
#or on arrays with partials
|
|
335
362
|
|
|
336
|
-
opts = {
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
json.array! @options, opts
|
|
363
|
+
opts = { cache: (->(d){ ['a', d.id] }), partial: ["blog_post", as: :blog_post] }
|
|
364
|
+
|
|
365
|
+
json.array! @options, opts do
|
|
366
|
+
end
|
|
341
367
|
```
|
|
342
368
|
|
|
343
369
|
### Deferment
|
|
344
370
|
|
|
345
|
-
You can defer rendering of expensive nodes in your content tree using the
|
|
346
|
-
|
|
371
|
+
You can defer rendering of expensive nodes in your content tree using the
|
|
372
|
+
`defer: :manual` option. Behind the scenes PropsTemplates will no-op the block
|
|
373
|
+
entirely and replace the value with a placeholder. A common use case would be
|
|
374
|
+
tabbed content that does not load until you click the tab.
|
|
375
|
+
|
|
376
|
+
When your client receives the payload, you may issue a second request to the
|
|
377
|
+
same endpoint to fetch any missing nodes. See [traversing nodes](#traversing)
|
|
347
378
|
|
|
348
|
-
|
|
379
|
+
There is also an `defer: :auto` option that you can use with [BreezyJS][1]. [BreezyJS][1]
|
|
380
|
+
will use the metadata from `json.deferred!` to issue a `remote` dispatch to fetch
|
|
381
|
+
the missing node and immutably graft it at the appropriate keypath in your Redux
|
|
382
|
+
store.
|
|
349
383
|
|
|
350
384
|
Usage:
|
|
351
385
|
|
|
352
386
|
```ruby
|
|
353
|
-
json.dashboard(defer: :
|
|
387
|
+
json.dashboard(defer: :manual) do
|
|
388
|
+
sleep 10
|
|
389
|
+
json.some_fancy_metric 42
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
# or you can explicitly pass a placeholder
|
|
394
|
+
|
|
395
|
+
json.dashboard(defer: [:manual, placeholder: {}]) do
|
|
354
396
|
sleep 10
|
|
355
397
|
json.some_fancy_metric 42
|
|
356
398
|
end
|
|
357
399
|
```
|
|
358
400
|
|
|
359
|
-
A
|
|
401
|
+
A auto option is available:
|
|
402
|
+
|
|
403
|
+
**Note** This is a [BreezyJS][1] specific functionality.
|
|
360
404
|
|
|
361
405
|
```ruby
|
|
362
|
-
json.dashboard(defer: :
|
|
406
|
+
json.dashboard(defer: :auto) do
|
|
363
407
|
sleep 10
|
|
364
408
|
json.some_fancy_metric 42
|
|
365
409
|
end
|
|
@@ -371,39 +415,51 @@ Finally in your `application.json.props`:
|
|
|
371
415
|
json.defers json.deferred!
|
|
372
416
|
```
|
|
373
417
|
|
|
374
|
-
|
|
375
|
-
If `:manual` is used, PropsTemplate will no-op the block and will not populate `json.deferred!`. Its up to you to [query](props-template.md#traversing_nodes) to fetch the node seperately. A common usecase would be tab content that does not load until you click the tab.
|
|
376
|
-
|
|
377
418
|
#### Working with arrays
|
|
378
|
-
The default behavior for deferements is to use the index of the collection to
|
|
419
|
+
The default behavior for deferements is to use the index of the collection to
|
|
420
|
+
identify an element.
|
|
421
|
+
|
|
422
|
+
**Note** If you are using this library with [BreezyJS][1], the `:auto` options will
|
|
423
|
+
generate `?_bzq=a.b.c.0.title` for `json.deferred!`.
|
|
379
424
|
|
|
380
425
|
If you wish to use an attribute to identify the element. You must:
|
|
381
|
-
|
|
382
|
-
|
|
426
|
+
|
|
427
|
+
1. Use the `:key` option on `json.array!`. This key refers to an attribute on
|
|
428
|
+
your collection item, and is used for `defer: :auto` to generate a keypath for
|
|
429
|
+
[BreezyJS][1]. If you are NOT using BreezyJS, you do not need to do this.
|
|
430
|
+
|
|
431
|
+
2. Implement `member_at`, on the [collection](#jsonarray). This will be called
|
|
432
|
+
by PropsTemplate to when [searching nodes](#traversing)
|
|
383
433
|
|
|
384
434
|
For example:
|
|
385
435
|
|
|
386
436
|
```ruby
|
|
387
|
-
require 'props_template/core_ext'
|
|
388
|
-
|
|
389
|
-
|
|
437
|
+
require 'props_template/core_ext'
|
|
438
|
+
data = [
|
|
439
|
+
{id: 1, name: 'foo'},
|
|
440
|
+
{id: 2, name: 'bar'}
|
|
441
|
+
]
|
|
390
442
|
|
|
391
443
|
json.posts
|
|
392
444
|
json.array! data, key: :some_id do |item|
|
|
445
|
+
# By using :key, props_template will append `json.some_id item.some_id`
|
|
446
|
+
# automatically
|
|
447
|
+
|
|
393
448
|
json.contact(defer: :auto) do
|
|
394
449
|
json.address '123 example drive'
|
|
395
450
|
end
|
|
396
|
-
|
|
397
|
-
# json.some_id item.some_id will be appended automatically to the end of the block
|
|
398
451
|
end
|
|
399
452
|
end
|
|
400
453
|
```
|
|
401
454
|
|
|
402
|
-
|
|
455
|
+
If you are using [BreezyJS][1], BreezyJS will, it will automatically kick off
|
|
456
|
+
`remote(?bzq=posts.some_id=1.contact)` and `remote(?bzq=posts.some_id=2.contact)`.
|
|
403
457
|
|
|
404
|
-
|
|
458
|
+
## Traversing
|
|
405
459
|
|
|
406
|
-
PropsTemplate has the ability to walk the tree you build, skipping execution of
|
|
460
|
+
PropsTemplate has the ability to walk the tree you build, skipping execution of
|
|
461
|
+
untargeted nodes. This feature is useful for selectively updating your frontend
|
|
462
|
+
state.
|
|
407
463
|
|
|
408
464
|
```ruby
|
|
409
465
|
traversal_path = ['data', 'details', 'personal']
|
|
@@ -411,7 +467,7 @@ traversal_path = ['data', 'details', 'personal']
|
|
|
411
467
|
json.data(search: traversal_path) do
|
|
412
468
|
json.details do
|
|
413
469
|
json.employment do
|
|
414
|
-
...more stuff
|
|
470
|
+
...more stuff
|
|
415
471
|
end
|
|
416
472
|
|
|
417
473
|
json.personal do
|
|
@@ -422,25 +478,28 @@ json.data(search: traversal_path) do
|
|
|
422
478
|
end
|
|
423
479
|
|
|
424
480
|
json.footer do
|
|
425
|
-
|
|
481
|
+
...
|
|
426
482
|
end
|
|
427
483
|
```
|
|
428
484
|
|
|
429
|
-
PropsTemplate will
|
|
485
|
+
PropsTemplate will walk depth first, walking only when it finds a matching key,
|
|
486
|
+
then executes the associated block, and repeats until it the node is found.
|
|
487
|
+
The above will output:
|
|
430
488
|
|
|
431
489
|
```json
|
|
432
490
|
{
|
|
433
|
-
data: {
|
|
434
|
-
name: 'james',
|
|
435
|
-
zipCode: 91210
|
|
491
|
+
"data": {
|
|
492
|
+
"name": 'james',
|
|
493
|
+
"zipCode": 91210
|
|
436
494
|
},
|
|
437
|
-
footer: {
|
|
438
|
-
|
|
495
|
+
"footer": {
|
|
496
|
+
...
|
|
439
497
|
}
|
|
440
498
|
}
|
|
441
499
|
```
|
|
442
500
|
|
|
443
|
-
|
|
501
|
+
Searching only works with blocks, and will NOT work with Scalars
|
|
502
|
+
("leaf" values). For example:
|
|
444
503
|
|
|
445
504
|
```ruby
|
|
446
505
|
traversal_path = ['data', 'details', 'personal', 'name'] <- not found
|
|
@@ -452,12 +511,11 @@ json.data(search: traversal_path) do
|
|
|
452
511
|
end
|
|
453
512
|
end
|
|
454
513
|
end
|
|
455
|
-
|
|
456
514
|
```
|
|
457
515
|
|
|
458
516
|
## Nodes that do not exist
|
|
459
517
|
|
|
460
|
-
Nodes that are not found will
|
|
518
|
+
Nodes that are not found will remove the branch where search was enabled on.
|
|
461
519
|
|
|
462
520
|
```ruby
|
|
463
521
|
traversal_path = ['data', 'details', 'does_not_exist']
|
|
@@ -471,17 +529,54 @@ json.data(search: traversal_path) do
|
|
|
471
529
|
end
|
|
472
530
|
|
|
473
531
|
json.footer do
|
|
474
|
-
|
|
532
|
+
...
|
|
475
533
|
end
|
|
476
|
-
|
|
477
534
|
```
|
|
478
535
|
|
|
479
536
|
The above will render:
|
|
480
537
|
|
|
481
|
-
```
|
|
538
|
+
```json
|
|
482
539
|
{
|
|
483
|
-
footer: {
|
|
540
|
+
"footer": {
|
|
484
541
|
...
|
|
485
542
|
}
|
|
486
543
|
}
|
|
487
544
|
```
|
|
545
|
+
|
|
546
|
+
## Layouts
|
|
547
|
+
A single layout is supported. To use, create an `application.json.props` in
|
|
548
|
+
`app/views/layouts`. Here's an example:
|
|
549
|
+
|
|
550
|
+
```ruby
|
|
551
|
+
json.data do
|
|
552
|
+
# template runs here.
|
|
553
|
+
yield json
|
|
554
|
+
end
|
|
555
|
+
|
|
556
|
+
json.header do
|
|
557
|
+
json.greeting "Hello"
|
|
558
|
+
end
|
|
559
|
+
|
|
560
|
+
json.footer do
|
|
561
|
+
json.greeting "Hello"
|
|
562
|
+
end
|
|
563
|
+
|
|
564
|
+
json.flash flash.to_h
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
**NOTE** PropsTemplate inverts the usual Rails rendering flow. PropsTemplate
|
|
568
|
+
will render Layout first, then the template when `yield json` is used.
|
|
569
|
+
|
|
570
|
+
## Contributing
|
|
571
|
+
|
|
572
|
+
See the [CONTRIBUTING] document. Thank you, [contributors]!
|
|
573
|
+
|
|
574
|
+
[CONTRIBUTING]: CONTRIBUTING.md
|
|
575
|
+
[contributors]: https://github.com/thoughtbot/props_template/graphs/contributors
|
|
576
|
+
|
|
577
|
+
## Special Thanks
|
|
578
|
+
|
|
579
|
+
Thanks to [turbostreamer](https://github.com/malomalo/turbostreamer) for the
|
|
580
|
+
inspiration.
|
|
581
|
+
|
|
582
|
+
[1]: https://github.com/thoughtbot/breezy
|
data/lib/props_template.rb
CHANGED
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.20.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Johny Ho
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2021-
|
|
11
|
+
date: 2021-06-03 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activesupport
|
|
@@ -52,8 +52,10 @@ dependencies:
|
|
|
52
52
|
- - ">="
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
54
|
version: '3.9'
|
|
55
|
-
description:
|
|
56
|
-
|
|
55
|
+
description: PropsTemplate is a direct-to-Oj, JBuilder-like DSL for building JSON.
|
|
56
|
+
It has support for Russian-Doll caching, layouts, and can be queried by giving the
|
|
57
|
+
root a key path.
|
|
58
|
+
email: johny@thoughtbot.com
|
|
57
59
|
executables: []
|
|
58
60
|
extensions: []
|
|
59
61
|
extra_rdoc_files: []
|
|
@@ -74,10 +76,11 @@ files:
|
|
|
74
76
|
- lib/props_template/layout_patch.rb
|
|
75
77
|
- lib/props_template/railtie.rb
|
|
76
78
|
- lib/props_template/searcher.rb
|
|
79
|
+
- lib/props_template/version.rb
|
|
77
80
|
- spec/layout_spec.rb
|
|
78
81
|
- spec/props_template_spec.rb
|
|
79
82
|
- spec/searcher_spec.rb
|
|
80
|
-
homepage: https://github.com/
|
|
83
|
+
homepage: https://github.com/thoughtbot/props_template/
|
|
81
84
|
licenses:
|
|
82
85
|
- MIT
|
|
83
86
|
metadata: {}
|
|
@@ -89,17 +92,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
89
92
|
requirements:
|
|
90
93
|
- - ">="
|
|
91
94
|
- !ruby/object:Gem::Version
|
|
92
|
-
version: '2.
|
|
95
|
+
version: '2.5'
|
|
93
96
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
94
97
|
requirements:
|
|
95
98
|
- - ">="
|
|
96
99
|
- !ruby/object:Gem::Version
|
|
97
100
|
version: '0'
|
|
98
101
|
requirements: []
|
|
99
|
-
rubygems_version: 3.1.
|
|
102
|
+
rubygems_version: 3.1.6
|
|
100
103
|
signing_key:
|
|
101
104
|
specification_version: 4
|
|
102
|
-
summary: A JSON builder
|
|
105
|
+
summary: A fast JSON builder
|
|
103
106
|
test_files:
|
|
104
107
|
- spec/searcher_spec.rb
|
|
105
108
|
- spec/layout_spec.rb
|