jsonity 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7837ec79aa7e71a84da9f8fda957c0217bd2691b
4
- data.tar.gz: 26ad97f8e6d9b9dcd3dad8c0155eab31a80c8d6b
3
+ metadata.gz: b5e0cbbf0655194ed77a8e96424d290e700cc6a6
4
+ data.tar.gz: c26576875dc473fd201e7f8ccd21940a642da05f
5
5
  SHA512:
6
- metadata.gz: e7535b1ce03cb5c6cb877aaf91fa0676f93eda13bc706db8ddeb5169bc443853f0112893dcd2cc20d5a60264d2226231a9b83dca599e86815cb75f37c5e64208
7
- data.tar.gz: 7b7cff2ba3ece3d3a5be9a9eb002ce8ebdc9c534537120cbc74736be1079b999621a9b90893c5c231fe5b0c999c33eb435196fa2a849bf8b9f604651059ca268
6
+ metadata.gz: 305a32a835c2695991915d9e35899c5080ec3c624dffd63eb54c4760d9107b0390c8c6fd43b10cf86e5135cf0ceca19b1996ac763dfc11d250c34c77af3a6c0b
7
+ data.tar.gz: 4ef7f0f1a7c647255cff9f469ef35f0a7027510f5bdb1e9764fe8e6964ab6b20d142d4d7bd0db4fb792ea4c8c7b7dabe56ed87058c1e7d57c0b16d088765b712
data/README.md CHANGED
@@ -1,24 +1,45 @@
1
1
  Jsonity
2
2
  =======
3
3
 
4
- **The most natural language for building JSON in Ruby**
4
+ **The most sexy language for building JSON in Ruby**
5
+
6
+ I'd been writing JSON API with [Jbuilder](https://github.com/rails/jbuilder), [RABL](https://github.com/nesquena/rabl) and [ActiveModel::Serializer](https://github.com/rails-api/active_model_serializers), but nothing of them meet my requirement and use case.
7
+
8
+ - Jbuilder is very verbose in syntax, and its functonalities of partial and mixin are actually weak
9
+ - RABL has simple syntax, but writing complex data structure with it is not very readable
10
+ - ActiveModel::Serializer is persuasive role in Rails architecture, but can get very useless when you need to fully control from controller what attributes of nested (associated) object to be included
11
+
12
+ So I chose to create new one -- Jsonity, which is simple and powerful JSON builder especially for JSON API representations.
13
+
14
+ - Simple and readable syntax even if it gets complex
15
+ - Flexible and arbitrary nodes
16
+ - Includable mixin
17
+ - Declarative attributes inclusion
18
+
19
+
20
+ Installation
21
+ ------------
22
+
23
+ Make sure to add the gem to your Gemfile.
24
+
25
+ ```ruby
26
+ gem 'jsonity'
27
+ ```
5
28
 
6
29
 
7
30
  Overview
8
31
  --------
9
32
 
10
33
  ```ruby
11
- @meta_pagination = ->(t) {
12
- t.meta!(inherit: true) { |meta|
34
+ @meta_pagination_mixin = ->(t) {
35
+ t.meta! { |meta|
13
36
  meta.total_pages
14
37
  meta.current_page
15
38
  }
16
39
  }
17
40
 
18
41
  Jsonity.build { |t|
19
- t <= @users
20
-
21
- t[].users!(inherit: true) { |user|
42
+ t[].users!(@users) { |user|
22
43
  user.id
23
44
  user.age
24
45
  user.full_name { |u| [u.first_name, u.last_name].join ' ' }
@@ -28,115 +49,113 @@ Jsonity.build { |t|
28
49
  }
29
50
  }
30
51
 
31
- t.(&@meta_pagination)
32
- }
33
- #=> {
34
- # "users": [
35
- # {
36
- # "id": 1,
37
- # "age": 21,
38
- # "full_name": "John Smith",
39
- # "avatar": {
40
- # "image_url": "http://example.com/john.png"
41
- # }
42
- # },
43
- # {
44
- # "id": 2,
45
- # "age": 37,
46
- # "full_name": "William Northington",
47
- # "avatar": {
48
- # "image_url": "http://example.com/william.png"
49
- # }
50
- # },
51
- # {
52
- # "id": 3,
53
- # "age": 29,
54
- # "full_name": "Samuel Miller",
55
- # "avatar": {
56
- # "image_url": "http://example.com/samuel.png"
57
- # }
58
- # }
59
- # ],
60
- # "meta": {
61
- # "total_pages": 1,
62
- # "current_page": 1
63
- # }
64
- # }
52
+ t.(@users, &@meta_pagination_mixin)
53
+ }
54
+ =begin
55
+ {
56
+ "users": [
57
+ {
58
+ "id": 1,
59
+ "age": 21,
60
+ "full_name": "John Smith",
61
+ "avatar": {
62
+ "image_url": "http://example.com/john.png"
63
+ }
64
+ },
65
+ {
66
+ "id": 2,
67
+ "age": 37,
68
+ "full_name": "William Northington",
69
+ "avatar": null
70
+ }
71
+ ],
72
+ "meta": {
73
+ "total_pages": 1,
74
+ "current_page": 1
75
+ }
76
+ }
77
+ =end
65
78
  ```
66
79
 
67
80
 
68
81
  Usage
69
82
  -----
70
83
 
71
- Make sure to add the gem to your Gemfile.
72
-
73
- ```ruby
74
- gem 'neo_json'
75
- ```
84
+ ### Object assignment
76
85
 
77
- Start writing object:
86
+ To declare the data object for use:
78
87
 
79
88
  ```ruby
80
89
  Jsonity.build { |t|
90
+ t <= @user
81
91
  # ...
82
92
  }
83
93
  ```
84
94
 
85
- ### Object assignment
86
-
87
- To declare the data object for use:
95
+ Or pass as an argument:
88
96
 
89
97
  ```ruby
90
- t <= @user
98
+ Jsonity.build(@user) { |user|
99
+ # ...
100
+ }
91
101
  ```
92
102
 
103
+
93
104
  ### Attribute nodes
94
105
 
95
106
  Basic usage of defining simple attributes:
96
107
 
97
108
  ```ruby
98
- t.id # @user.id
99
- t.age # @user.age
109
+ Jsonity.build(@user) { |user|
110
+ user.id # @user.id
111
+ user.age # @user.age
112
+ }
113
+ =begin
114
+ {
115
+ "id": 123,
116
+ "age": 27
117
+ }
118
+ =end
100
119
  ```
101
120
 
102
121
  Or you can use custom attributes in flexible ways:
103
122
 
104
123
  ```ruby
105
- t.full_name { |u| [u.first_name, u.last_name].join ' ' } # u = @user
106
- t.russian_roulette { rand(1..10) } # block parameter isn't required
107
- t.with_object(Time) { |t| t.now } # now, t = Time
108
- t.seventeen 17 # block can be omitted
109
- ```
124
+ Jsonity.build(@user) { |user|
125
+ # create full_name from @user.first_name and @user.last_name
126
+ user.full_name { |u| [u.first_name, u.last_name].join ' ' }
110
127
 
111
- Aliased attributes works well as you expected:
112
-
113
- ```ruby
114
- # show `id` as `my_id`
115
- t.my_id &:id
116
- ```
128
+ # block parameter isn't required
129
+ user.russian_roulette { rand(1..10) }
117
130
 
118
- ### Automatic attributes inclusion
131
+ # or with specified object
132
+ user.feature_time(Time.now) { |now| now + 1.years }
119
133
 
120
- If you set `attr_json` in any class, the specified attributes will automatically be included:
134
+ # block can be omitted if the value is constant
135
+ user.seventeen 17
136
+ }
137
+ =begin
138
+ {
139
+ "full_name": "John Smith",
140
+ "russian_roulette": 4,
141
+ "feature_time": "2015-09-13 12:32:39 +0900",
142
+ "seventeen": 17
143
+ }
144
+ =end
145
+ ```
121
146
 
147
+ Aliased attributes works well as you expected:
148
+
122
149
  ```ruby
123
- class Sample < Struct.new(:id, :foo)
124
- attr_json :id, :foo
125
- end
126
-
127
- @sample = Sample.new 123, 'foo!'
128
-
129
- Jsonity.build { |t|
130
- t.sample!(@sample) { |t|
131
- # leave empty inside
132
- }
150
+ Jsonity.build(@user) { |user|
151
+ # show `id` as `my_id`
152
+ user.my_id &:id
133
153
  }
134
- #=> {
135
- # "sample": {
136
- # "id": 123,
137
- # "foo": "foo!"
138
- # }
139
- # }
154
+ =begin
155
+ {
156
+ "my_id": 123
157
+ }
158
+ =end
140
159
  ```
141
160
 
142
161
  ### Hash nodes
@@ -144,7 +163,7 @@ Jsonity.build { |t|
144
163
  With name suffixed with `!`, nested object can be included:
145
164
 
146
165
  ```ruby
147
- t.user! { |user|
166
+ Jsonity.build(@user) { |user|
148
167
  user.name # @user.name
149
168
 
150
169
  user.avatar! { |avatar|
@@ -153,89 +172,152 @@ t.user! { |user|
153
172
  avatar.height # @user.avatar.height
154
173
  }
155
174
  }
156
- ```
157
-
158
- If `@user.avatar = nil`, the output will be like this:
175
+ =begin
176
+ Assume that `@user.avatar` is `nil`,
159
177
 
160
- ```javascipt
161
178
  {
162
- "user": {
163
- "name": "John Smith",
164
- "avatar": {
165
- "image_url": null,
166
- "width": null,
167
- "height": null
168
- }
179
+ "name": "John Smith",
180
+ "avatar": {
181
+ "image_url": null,
182
+ "width": null,
183
+ "height": null
169
184
  }
170
185
  }
186
+ =end
171
187
  ```
172
188
 
173
189
  On the other hand, use `?` as suffix, the whole object become `null`:
174
190
 
175
191
  ```ruby
176
- t.user! { |user|
192
+ Jsonity.build(@user) { |user|
177
193
  user.name
178
194
 
179
- user.avatar? { |avatar|
195
+ user.avatar? { |avatar| # <-- look, prefix is `?`
180
196
  avatar.image_url
181
197
  avatar.width
182
198
  avatar.height
183
199
  }
184
200
  }
201
+ =begin
202
+ Assume that `@user.avatar` is `nil`,
203
+
204
+ {
205
+ "name": "John Smith",
206
+ "avatar": null
207
+ }
208
+ =end
209
+ ```
210
+
211
+ Explicitly specify an object to use inside a block:
212
+
213
+ ```ruby
214
+ Jsonity.build { |t|
215
+ t.home!(@user.hometown_address) { |home|
216
+ home.street # @user.hometown_address.street
217
+ home.zip
218
+ home.city
219
+ home.state
220
+ }
221
+ }
222
+ =begin
223
+ {
224
+ "home": {
225
+ "street": "4611 Armbrester Drive",
226
+ "zip": "90017",
227
+ "city": "Los Angeles",
228
+ "state": "CA"
229
+ }
230
+ }
231
+ =end
185
232
  ```
186
233
 
187
- and the output will be:
234
+ Or a block can inherit the parent object:
188
235
 
189
- ```javascipt
236
+ ```ruby
237
+ Jsonity.build { |t|
238
+ t.user!(@user) { |user|
239
+ t.profile!(inherit: true) { |profile|
240
+ profile.name # @user.name
241
+ }
242
+ }
243
+ }
244
+ =begin
190
245
  {
191
246
  "user": {
192
- "name": "John Smith",
193
- "avatar": null
247
+ "profile": {
248
+ "name": "John Smith"
249
+ }
194
250
  }
195
251
  }
252
+ =end
196
253
  ```
197
254
 
198
- Explicitly set an object to use inside a block:
255
+ ### Automatic attributes inclusion
256
+
257
+ If you set `attr_json` in any class, **the specified attributes will automatically be included**:
199
258
 
200
259
  ```ruby
201
- t.home?(@user.hometown_address) { |home|
202
- home.street # @user.hometown_address.street
203
- home.zip
204
- home.city
205
- home.state
206
- }
260
+ class Sample < Struct.new(:id, :foo, :bar)
261
+ attr_json :id, :foo
262
+ end
263
+
264
+ @sample = Sample.new 123, 'foo!', 'bar!!'
207
265
  ```
208
266
 
209
- Or blocks can inherit the parent object:
267
+ and then,
210
268
 
211
269
  ```ruby
212
- t.user! { |user|
213
- t.my!(inherit: true) { |my|
214
- my.name # @user.name
270
+ Jsonity.build { |t|
271
+ t.sample! @sample
272
+ }
273
+ =begin
274
+ {
275
+ "sample": {
276
+ "id": 123,
277
+ "foo": "foo!"
215
278
  }
216
279
  }
280
+ =end
217
281
  ```
218
282
 
219
- ### Array nodes
220
-
221
- Including a collection of objects, just use `t[]` and write the same syntax of hash node:
283
+ Still you can create any kinds of nodes with a block:
222
284
 
223
285
  ```ruby
224
- t[].friends! { |friend|
225
- friend.name
286
+ Jsonity.build { |t|
287
+ t.sample!(@sample) { |sample|
288
+ sample.bar { |bar| "this is #{bar}" }
289
+ }
290
+ }
291
+ =begin
292
+ {
293
+ "sample": {
294
+ "id": 123,
295
+ "foo": "foo!",
296
+ "bar": "this is bar!!"
297
+ }
226
298
  }
299
+ =end
227
300
  ```
228
301
 
229
- and the output JSON will be:
230
302
 
231
- ```javascipt
303
+ ### Array nodes
304
+
305
+ Including a collection of objects, just use `[]` and write the same syntax of hash node:
306
+
307
+ ```ruby
308
+ Jsonity.build(@user) { |user|
309
+ user[].friends! { |friend|
310
+ friend.name # @user.friends[i].name
311
+ }
312
+ }
313
+ =begin
232
314
  {
233
315
  "friends": [
234
- {
235
- name: "John Smith"
236
- }
316
+ { "name": "John Smith" },
317
+ { "name": "William Northington" }
237
318
  ]
238
319
  }
320
+ =end
239
321
  ```
240
322
 
241
323
  Similar to hash nodes in naming convention,
@@ -246,10 +328,10 @@ Also passing the object or inheritance can be done in the same way as hash nodes
246
328
 
247
329
  ### Mixin / Scope
248
330
 
249
- Since Jsonity aim to be simple and light, use plain `Proc` to fullfill functonality of mixin.
331
+ Since Jsonity aim to be simple and light, **use plain `Proc`** to fullfill functonality of mixin.
250
332
 
251
333
  ```ruby
252
- timestamp_mixin = ->(t) {
334
+ @timestamps_mixin = ->(t) {
253
335
  t.created_at
254
336
  t.updated_at
255
337
  }
@@ -258,29 +340,54 @@ timestamp_mixin = ->(t) {
258
340
  and then,
259
341
 
260
342
  ```ruby
261
- t.user! { |user|
262
- user.(&timestamp_mixin)
343
+ Jsonity.build { |t|
344
+ t.user!(@user) { |user|
345
+ user.(&@timestamps_mixin)
346
+ }
263
347
  }
348
+ =begin
349
+ {
350
+ "user": {
351
+ "created_at": "2014-09-10 10:41:07 +0900",
352
+ "updated_at": "2014-09-13 12:55:56 +0900"
353
+ }
354
+ }
355
+ =end
264
356
  ```
265
357
 
266
- In case you might use different object in mixin, you can pass the object in the first argument:
358
+ In case you might explicitly **specify an object to use** in mixin, you can do by passing it in the first argument:
267
359
 
268
360
  ```ruby
269
- t.(@other_user, &timestamps)
361
+ Jsonity.build { |t|
362
+ t.(@user, &@timestamps_mixin)
363
+ }
364
+ =begin
365
+ {
366
+ "created_at": "2014-09-10 10:41:07 +0900",
367
+ "updated_at": "2014-09-13 12:55:56 +0900"
368
+ }
369
+ =end
270
370
  ```
271
371
 
272
- So you take this functonality for scope:
372
+ So you take this functonality for **scope**:
273
373
 
274
374
  ```ruby
275
- t.(@other_user) { |other_user|
276
- other_user.name
375
+ Jsonity.build { |t|
376
+ t.(@user) { |user|
377
+ user.name
378
+ }
277
379
  }
380
+ =begin
381
+ {
382
+ "name": "John Smith"
383
+ }
384
+ =end
278
385
  ```
279
386
 
280
387
  #### Mixining nested object and merging
281
388
 
282
389
  ```ruby
283
- meta_pagination_mixin = ->(t) {
390
+ @meta_pagination_mixin = ->(t) {
284
391
  t.meta! { |meta|
285
392
  meta.total_pages
286
393
  meta.current_page
@@ -291,46 +398,41 @@ meta_pagination_mixin = ->(t) {
291
398
  and use this mixin like:
292
399
 
293
400
  ```ruby
294
- t[].people!(@people) { |person|
295
- # ...
296
- }
297
-
298
- t.(@people, &meta_pagination_mixin)
401
+ Jsonity.build { |t|
402
+ t.(@people, &@meta_pagination_mixin)
299
403
 
300
- t.meta! { |meta|
301
- meta.total_count @people.count
404
+ t.meta! { |meta|
405
+ meta.total_count @people.count
406
+ }
302
407
  }
303
- ```
304
-
305
- the output become:
408
+ =begin
409
+ Notice that two objects `meta!` got merged.
306
410
 
307
- ```javascript
308
411
  {
309
- "people": [
310
- // ...
311
- ],
312
412
  "meta": {
313
413
  "total_pages": 5,
314
414
  "current_page": 1,
315
415
  "total_count": 123
316
416
  }
317
417
  }
418
+ =end
318
419
  ```
319
420
 
320
- Notice that two objects `meta!` got merged.
321
421
 
322
- ### Conditions
422
+ ### Using object
323
423
 
324
- Simply you can use `if` or `unless` statement inside the block:
424
+ You can get the current object as a second block parameter.
325
425
 
326
- ```
327
- t[].people! { |person|
328
- unless person.private_member?
329
- person.name
330
- person.age
331
- end
426
+ ```ruby
427
+ Jsonity.build { |t|
428
+ t[].people!(@people) { |person, person_obj|
429
+ unless person_obj.private_member?
430
+ person.name
431
+ person.age
432
+ end
332
433
 
333
- person.cv if person.looking_for_job?
434
+ person.cv if person_obj.looking_for_job?
435
+ }
334
436
  }
335
437
  ```
336
438
 
@@ -338,7 +440,7 @@ t[].people! { |person|
338
440
  With Rails
339
441
  ----------
340
442
 
341
- Helper method is available for rendering with Jsonity:
443
+ Helper method is available in controller for rendering with Jsonity:
342
444
 
343
445
  ```ruby
344
446
  render_json(status: :ok) { |t|
data/jsonity.gemspec CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
8
8
  spec.version = Jsonity::VERSION
9
9
  spec.authors = ['Yuki Iwanaga']
10
10
  spec.email = ['yuki@creasty.com']
11
- spec.summary = 'The most natural language for building JSON in Ruby'
12
- spec.description = 'The most natural language for building JSON in Ruby'
11
+ spec.summary = 'The most sexy language for building JSON in Ruby'
12
+ spec.description = 'The most sexy language for building JSON in Ruby'
13
13
  spec.homepage = 'https://github.com/creasty/jsonity'
14
14
  spec.license = 'MIT'
15
15
 
@@ -1,3 +1,3 @@
1
1
  module Jsonity
2
- VERSION = '1.0.0'
2
+ VERSION = '1.0.1'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsonity
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yuki Iwanaga
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-12 00:00:00.000000000 Z
11
+ date: 2014-09-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -38,7 +38,7 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.3'
41
- description: The most natural language for building JSON in Ruby
41
+ description: The most sexy language for building JSON in Ruby
42
42
  email:
43
43
  - yuki@creasty.com
44
44
  executables: []
@@ -80,5 +80,5 @@ rubyforge_project:
80
80
  rubygems_version: 2.2.2
81
81
  signing_key:
82
82
  specification_version: 4
83
- summary: The most natural language for building JSON in Ruby
83
+ summary: The most sexy language for building JSON in Ruby
84
84
  test_files: []