jsonapi-resources 0.4.2 → 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -2
- data/README.md +103 -71
- data/Rakefile +2 -2
- data/jsonapi-resources.gemspec +2 -2
- data/lib/jsonapi-resources.rb +0 -1
- data/lib/jsonapi/active_record_operations_processor.rb +10 -2
- data/lib/jsonapi/acts_as_resource_controller.rb +26 -24
- data/lib/jsonapi/association.rb +50 -15
- data/lib/jsonapi/callbacks.rb +1 -2
- data/lib/jsonapi/configuration.rb +8 -24
- data/lib/jsonapi/error.rb +1 -2
- data/lib/jsonapi/error_codes.rb +3 -1
- data/lib/jsonapi/exceptions.rb +59 -47
- data/lib/jsonapi/include_directives.rb +11 -11
- data/lib/jsonapi/mime_types.rb +2 -2
- data/lib/jsonapi/operation.rb +28 -11
- data/lib/jsonapi/operations_processor.rb +16 -5
- data/lib/jsonapi/paginator.rb +19 -19
- data/lib/jsonapi/request.rb +175 -196
- data/lib/jsonapi/resource.rb +158 -105
- data/lib/jsonapi/resource_serializer.rb +37 -26
- data/lib/jsonapi/resources/version.rb +2 -2
- data/lib/jsonapi/response_document.rb +5 -4
- data/lib/jsonapi/routing_ext.rb +24 -19
- data/test/controllers/controller_test.rb +261 -31
- data/test/fixtures/active_record.rb +206 -8
- data/test/fixtures/book_comments.yml +2 -1
- data/test/fixtures/books.yml +1 -0
- data/test/fixtures/documents.yml +3 -0
- data/test/fixtures/people.yml +8 -1
- data/test/fixtures/pictures.yml +15 -0
- data/test/fixtures/products.yml +3 -0
- data/test/fixtures/vehicles.yml +8 -0
- data/test/helpers/{hash_helpers.rb → assertions.rb} +6 -1
- data/test/integration/requests/request_test.rb +14 -3
- data/test/integration/routes/routes_test.rb +47 -0
- data/test/test_helper.rb +27 -4
- data/test/unit/serializer/include_directives_test.rb +5 -0
- data/test/unit/serializer/polymorphic_serializer_test.rb +384 -0
- data/test/unit/serializer/serializer_test.rb +19 -1
- metadata +14 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 797927f93aedcb2dab47c655c02b3b0fc585ae3a
|
4
|
+
data.tar.gz: 679a57fb31f8a64b19735130d70bd79eef9b46ad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 39a597f4b31a1273f4a7a71bf3b46ea0a19251b235a2fb8212c3452d959c6b01094a33420bad1fc7ac69d1c082d8193cb99d7c73e5f541c747c60d3503de1190
|
7
|
+
data.tar.gz: 819a12d466c075c127b9a9c6863b675fd3dc28a21f011022132c460badeb8e102745aacfb9cc4c6cab4c60d4f69d41f9b22fbbe8c1804ad4b92c2c0a43006a54
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
# JSONAPI::Resources [![Build Status](https://secure.travis-ci.org/cerebris/jsonapi-resources.png?branch=master)](http://travis-ci.org/cerebris/jsonapi-resources)
|
2
2
|
|
3
|
-
`JSONAPI::Resources`, or "JR", provides a framework for developing a server that complies with the
|
3
|
+
`JSONAPI::Resources`, or "JR", provides a framework for developing a server that complies with the
|
4
4
|
[JSON API](http://jsonapi.org/) specification.
|
5
5
|
|
6
|
-
Like JSON API itself, JR's design is focused on the resources served by an API. JR needs little more than a definition
|
6
|
+
Like JSON API itself, JR's design is focused on the resources served by an API. JR needs little more than a definition
|
7
7
|
of your resources, including their attributes and relationships, to make your server compliant with JSON API.
|
8
8
|
|
9
|
-
JR is designed to work with Rails 4.0+, and provides custom routes, controllers, and serializers. JR's resources may be
|
9
|
+
JR is designed to work with Rails 4.0+, and provides custom routes, controllers, and serializers. JR's resources may be
|
10
10
|
backed by ActiveRecord models or by custom objects.
|
11
11
|
|
12
12
|
## Demo App
|
@@ -15,7 +15,7 @@ We have a simple demo app, called [Peeps](https://github.com/cerebris/peeps), av
|
|
15
15
|
|
16
16
|
## Client Libraries
|
17
17
|
|
18
|
-
JSON API maintains a (non-verified) listing of [client libraries](http://jsonapi.org/implementations/#client-libraries)
|
18
|
+
JSON API maintains a (non-verified) listing of [client libraries](http://jsonapi.org/implementations/#client-libraries)
|
19
19
|
which *should* be compatible with JSON API compliant server implementations such as JR.
|
20
20
|
|
21
21
|
## Installation
|
@@ -36,10 +36,10 @@ Or install it yourself as:
|
|
36
36
|
|
37
37
|
### Resources
|
38
38
|
|
39
|
-
Resources define the public interface to your API. A resource defines which attributes are exposed, as well as
|
39
|
+
Resources define the public interface to your API. A resource defines which attributes are exposed, as well as
|
40
40
|
relationships to other resources.
|
41
41
|
|
42
|
-
Resource definitions should by convention be placed in a directory under app named resources, `app/resources`. The class
|
42
|
+
Resource definitions should by convention be placed in a directory under app named resources, `app/resources`. The class
|
43
43
|
name should be the single underscored name of the model that backs the resource with `_resource.rb` appended. For example,
|
44
44
|
a `Contact` model's resource should have a class named `ContactResource` defined in a file named `contact_resource.rb`.
|
45
45
|
|
@@ -56,7 +56,7 @@ end
|
|
56
56
|
|
57
57
|
#### Attributes
|
58
58
|
|
59
|
-
Any of a resource's attributes that are accessible must be explicitly declared. Single attributes can be declared using
|
59
|
+
Any of a resource's attributes that are accessible must be explicitly declared. Single attributes can be declared using
|
60
60
|
the `attribute` method, and multiple attributes can be declared with the `attributes` method on the resource class.
|
61
61
|
|
62
62
|
For example:
|
@@ -68,10 +68,10 @@ class ContactResource < JSONAPI::Resource
|
|
68
68
|
end
|
69
69
|
```
|
70
70
|
|
71
|
-
This resource has 4 defined attributes: `name_first`, `name_last`, `email`, `twitter`, as well as the automatically
|
71
|
+
This resource has 4 defined attributes: `name_first`, `name_last`, `email`, `twitter`, as well as the automatically
|
72
72
|
defined attributes `id` and `type`. By default these attributes must exist on the model that is handled by the resource.
|
73
73
|
|
74
|
-
A resource object wraps a Ruby object, usually an `ActiveModel` record, which is available as the `@model` variable.
|
74
|
+
A resource object wraps a Ruby object, usually an `ActiveModel` record, which is available as the `@model` variable.
|
75
75
|
This allows a resource's methods to access the underlying model.
|
76
76
|
|
77
77
|
For example, a computed attribute for `full_name` could be defined as such:
|
@@ -89,7 +89,7 @@ end
|
|
89
89
|
|
90
90
|
##### Fetchable Attributes
|
91
91
|
|
92
|
-
By default all attributes are assumed to be fetchable. The list of fetchable attributes can be filtered by overriding
|
92
|
+
By default all attributes are assumed to be fetchable. The list of fetchable attributes can be filtered by overriding
|
93
93
|
the `fetchable_fields` method.
|
94
94
|
|
95
95
|
Here's an example that prevents guest users from seeing the `email` field:
|
@@ -115,7 +115,7 @@ value).
|
|
115
115
|
|
116
116
|
##### Creatable and Updatable Attributes
|
117
117
|
|
118
|
-
By default all attributes are assumed to be updatable and creatable. To prevent some attributes from being accepted by
|
118
|
+
By default all attributes are assumed to be updatable and creatable. To prevent some attributes from being accepted by
|
119
119
|
the `update` or `create` methods, override the `self.updatable_fields` and `self.creatable_fields` methods on a resource.
|
120
120
|
|
121
121
|
This example prevents `full_name` from being set:
|
@@ -145,7 +145,7 @@ By using the context you have the option to determine the creatable and updatabl
|
|
145
145
|
|
146
146
|
JR supports [sorting primary resources by multiple sort criteria](http://jsonapi.org/format/#fetching-sorting).
|
147
147
|
|
148
|
-
By default all attributes are assumed to be sortable. To prevent some attributes from being sortable, override the
|
148
|
+
By default all attributes are assumed to be sortable. To prevent some attributes from being sortable, override the
|
149
149
|
`self.sortable_fields` method on a resource.
|
150
150
|
|
151
151
|
Here's an example that prevents sorting by post's `body`:
|
@@ -162,7 +162,7 @@ end
|
|
162
162
|
|
163
163
|
##### Attribute Formatting
|
164
164
|
|
165
|
-
Attributes can have a `Format`. By default all attributes use the default formatter. If an attribute has the `format`
|
165
|
+
Attributes can have a `Format`. By default all attributes use the default formatter. If an attribute has the `format`
|
166
166
|
option set the system will attempt to find a formatter based on this name. In the following example the `last_login_time`
|
167
167
|
will be returned formatted to a certain time zone:
|
168
168
|
|
@@ -178,12 +178,12 @@ updating the attribute. See the [Value Formatters](#value-formatters) section fo
|
|
178
178
|
|
179
179
|
#### Primary Key
|
180
180
|
|
181
|
-
Resources are always represented using a key of `id`. If the underlying model does not use `id` as the primary key you
|
182
|
-
can use the `primary_key` method to tell the resource which field on the model to use as the primary key. Note: this
|
183
|
-
doesn't have to be the actual primary key of the model. For example you may wish to use integers internally and a
|
181
|
+
Resources are always represented using a key of `id`. If the underlying model does not use `id` as the primary key you
|
182
|
+
can use the `primary_key` method to tell the resource which field on the model to use as the primary key. Note: this
|
183
|
+
doesn't have to be the actual primary key of the model. For example you may wish to use integers internally and a
|
184
184
|
different scheme publicly.
|
185
185
|
|
186
|
-
By default only integer values are allowed for primary key. To change this behavior you can override
|
186
|
+
By default only integer values are allowed for primary key. To change this behavior you can override
|
187
187
|
`verify_key` class method:
|
188
188
|
|
189
189
|
```ruby
|
@@ -201,7 +201,7 @@ end
|
|
201
201
|
|
202
202
|
#### Model Name
|
203
203
|
|
204
|
-
The name of the underlying model is inferred from the Resource name. It can be overridden by use of the `model_name`
|
204
|
+
The name of the underlying model is inferred from the Resource name. It can be overridden by use of the `model_name`
|
205
205
|
method. For example:
|
206
206
|
|
207
207
|
```ruby
|
@@ -239,34 +239,64 @@ end
|
|
239
239
|
##### Options
|
240
240
|
|
241
241
|
The association methods support the following options:
|
242
|
+
|
242
243
|
* `class_name` - a string specifying the underlying class for the related resource
|
243
|
-
* `foreign_key` - the method on the resource used to fetch the related resource. Defaults to `<resource_name>_id` for
|
244
|
-
has_one and `<resource_name>_ids` for has_many relationships.
|
244
|
+
* `foreign_key` - the method on the resource used to fetch the related resource. Defaults to `<resource_name>_id` for has_one and `<resource_name>_ids` for has_many relationships.
|
245
245
|
* `acts_as_set` - allows the entire set of related records to be replaced in one operation. Defaults to false if not set.
|
246
|
+
* `polymorphic` - set to true to identify associations that are polymorphic.
|
247
|
+
* `relation_name` - the name of the relation to use on the model. A lambda may be provided which allows conditional selection of the relation based on the context.
|
246
248
|
|
247
249
|
Examples:
|
248
250
|
|
249
251
|
```ruby
|
250
|
-
|
252
|
+
class CommentResource < JSONAPI::Resource
|
251
253
|
attributes :body
|
252
254
|
has_one :post
|
253
255
|
has_one :author, class_name: 'Person'
|
254
256
|
has_many :tags, acts_as_set: true
|
255
|
-
|
256
|
-
```
|
257
|
+
end
|
257
258
|
|
258
|
-
```ruby
|
259
259
|
class ExpenseEntryResource < JSONAPI::Resource
|
260
260
|
attributes :cost, :transaction_date
|
261
261
|
|
262
262
|
has_one :currency, class_name: 'Currency', foreign_key: 'currency_code'
|
263
263
|
has_one :employee
|
264
264
|
end
|
265
|
+
|
266
|
+
class TagResource < JSONAPI::Resource
|
267
|
+
attributes :name
|
268
|
+
has_one :taggable, polymorphic: true
|
269
|
+
end
|
270
|
+
```
|
271
|
+
|
272
|
+
```ruby
|
273
|
+
class BookResource < JSONAPI::Resource
|
274
|
+
|
275
|
+
# Only book_admins may see unapproved comments for a book. Using
|
276
|
+
# a lambda to select the correct relation on the model
|
277
|
+
has_many :book_comments, relation_name: -> (options = {}) {
|
278
|
+
context = options[:context]
|
279
|
+
current_user = context ? context[:current_user] : nil
|
280
|
+
|
281
|
+
unless current_user && current_user.book_admin
|
282
|
+
:approved_book_comments
|
283
|
+
else
|
284
|
+
:book_comments
|
285
|
+
end
|
286
|
+
}
|
287
|
+
...
|
288
|
+
end
|
289
|
+
|
290
|
+
The polymorphic association will require the resource and controller to exist, although routing to them will cause an error.
|
291
|
+
|
292
|
+
```ruby
|
293
|
+
class TaggableResource < JSONAPI::Resource; end
|
294
|
+
class TaggablesController < JSONAPI::ResourceController; end
|
265
295
|
```
|
266
296
|
|
267
297
|
#### Filters
|
268
298
|
|
269
|
-
Filters for locating objects of the resource type are specified in the resource definition. Single filters can be
|
299
|
+
Filters for locating objects of the resource type are specified in the resource definition. Single filters can be
|
270
300
|
declared using the `filter` method, and multiple filters can be declared with the `filters` method on the resource class.
|
271
301
|
|
272
302
|
For example:
|
@@ -280,6 +310,8 @@ class ContactResource < JSONAPI::Resource
|
|
280
310
|
end
|
281
311
|
```
|
282
312
|
|
313
|
+
Then a request could pass in a filter for example `http://example.com/contacts?filter[name_last]=Smith` and the system will find all people where the last name exactly matches Smith.
|
314
|
+
|
283
315
|
##### Default Filters
|
284
316
|
|
285
317
|
A default filter may be defined for a resource using the `default` option on the `filter` method. This default is used
|
@@ -292,7 +324,7 @@ For example:
|
|
292
324
|
attributes :body, :status
|
293
325
|
has_one :post
|
294
326
|
has_one :author
|
295
|
-
|
327
|
+
|
296
328
|
filter :status, default: 'published,pending'
|
297
329
|
end
|
298
330
|
```
|
@@ -301,13 +333,13 @@ The default value is used as if it came from the request.
|
|
301
333
|
|
302
334
|
##### Finders
|
303
335
|
|
304
|
-
Basic finding by filters is supported by resources. This is implemented in the `find` and `find_by_key` finder methods.
|
336
|
+
Basic finding by filters is supported by resources. This is implemented in the `find` and `find_by_key` finder methods.
|
305
337
|
Currently this is implemented for `ActiveRecord` based resources. The finder methods rely on the `records` method to get
|
306
338
|
an `Arel` relation. It is therefore possible to override `records` to affect the three find related methods.
|
307
339
|
|
308
340
|
###### Customizing base records for finder methods
|
309
341
|
|
310
|
-
If you need to change the base records on which `find` and `find_by_key` operate, you can override the `records` method
|
342
|
+
If you need to change the base records on which `find` and `find_by_key` operate, you can override the `records` method
|
311
343
|
on the resource class.
|
312
344
|
|
313
345
|
For example to allow a user to only retrieve his own posts you can do the following:
|
@@ -323,7 +355,7 @@ class PostResource < JSONAPI::Resource
|
|
323
355
|
end
|
324
356
|
```
|
325
357
|
|
326
|
-
When you create a relationship, a method is created to fetch record(s) for that relationship. This method calls
|
358
|
+
When you create a relationship, a method is created to fetch record(s) for that relationship. This method calls
|
327
359
|
`records_for(association_name)` by default.
|
328
360
|
|
329
361
|
```ruby
|
@@ -361,7 +393,7 @@ end
|
|
361
393
|
|
362
394
|
###### Applying Filters
|
363
395
|
|
364
|
-
The `apply_filter` method is called to apply each filter to the `Arel` relation. You may override this method to gain
|
396
|
+
The `apply_filter` method is called to apply each filter to the `Arel` relation. You may override this method to gain
|
365
397
|
control over how the filters are applied to the `Arel` relation.
|
366
398
|
|
367
399
|
This example shows how you can implement different approaches for different filters.
|
@@ -388,7 +420,7 @@ end
|
|
388
420
|
|
389
421
|
###### Override finder methods
|
390
422
|
|
391
|
-
Finally if you have more complex requirements for finding you can override the `find` and `find_by_key` methods on the
|
423
|
+
Finally if you have more complex requirements for finding you can override the `find` and `find_by_key` methods on the
|
392
424
|
resource class.
|
393
425
|
|
394
426
|
Here's an example that defers the `find` operation to a `current_user` set on the `context` option:
|
@@ -414,24 +446,24 @@ end
|
|
414
446
|
|
415
447
|
#### Pagination
|
416
448
|
|
417
|
-
Pagination is performed using a `paginator`, which is a class responsible for parsing the `page` request parameters and
|
449
|
+
Pagination is performed using a `paginator`, which is a class responsible for parsing the `page` request parameters and
|
418
450
|
applying the pagination logic to the results.
|
419
451
|
|
420
452
|
##### Paginators
|
421
453
|
|
422
|
-
`JSONAPI::Resource` supports several pagination methods by default, and allows you to implement a custom system if the
|
454
|
+
`JSONAPI::Resource` supports several pagination methods by default, and allows you to implement a custom system if the
|
423
455
|
defaults do not meet your needs.
|
424
456
|
|
425
457
|
###### Paged Paginator
|
426
458
|
|
427
|
-
The `paged` `paginator` returns results based on pages of a fixed size. Valid `page` parameters are `number` and `size`.
|
428
|
-
If `number` is omitted the first page is returned. If `size` is omitted the `default_page_size` from the configuration
|
459
|
+
The `paged` `paginator` returns results based on pages of a fixed size. Valid `page` parameters are `number` and `size`.
|
460
|
+
If `number` is omitted the first page is returned. If `size` is omitted the `default_page_size` from the configuration
|
429
461
|
settings is used.
|
430
462
|
|
431
463
|
###### Offset Paginator
|
432
464
|
|
433
|
-
The `offset` `paginator` returns results based on an offset from the beginning of the resultset. Valid `page` parameters
|
434
|
-
are `offset` and `limit`. If `offset` is omitted a value of 0 will be used. If `limit` is omitted the `default_page_size`
|
465
|
+
The `offset` `paginator` returns results based on an offset from the beginning of the resultset. Valid `page` parameters
|
466
|
+
are `offset` and `limit`. If `offset` is omitted a value of 0 will be used. If `limit` is omitted the `default_page_size`
|
435
467
|
from the configuration settings is used.
|
436
468
|
|
437
469
|
###### Custom Paginators
|
@@ -457,7 +489,7 @@ end
|
|
457
489
|
|
458
490
|
##### Paginator Configuration
|
459
491
|
|
460
|
-
The default paginator, which will be used for all resources, is set using `JSONAPI.configure`. For example, in your
|
492
|
+
The default paginator, which will be used for all resources, is set using `JSONAPI.configure`. For example, in your
|
461
493
|
`config/initializers/jsonapi_resources.rb`:
|
462
494
|
|
463
495
|
```ruby
|
@@ -472,7 +504,7 @@ end
|
|
472
504
|
|
473
505
|
If no `default_paginator` is configured, pagination will be disabled by default.
|
474
506
|
|
475
|
-
Paginators can also be set at the resource-level, which will override the default setting. This is done using the
|
507
|
+
Paginators can also be set at the resource-level, which will override the default setting. This is done using the
|
476
508
|
`paginator` method:
|
477
509
|
|
478
510
|
```ruby
|
@@ -488,7 +520,7 @@ To disable pagination in a resource, specify `:none` for `paginator`.
|
|
488
520
|
|
489
521
|
#### Callbacks
|
490
522
|
|
491
|
-
`ActiveSupport::Callbacks` is used to provide callback functionality, so the behavior is very similar to what you may be
|
523
|
+
`ActiveSupport::Callbacks` is used to provide callback functionality, so the behavior is very similar to what you may be
|
492
524
|
used to from `ActiveRecord`.
|
493
525
|
|
494
526
|
For example, you might use a callback to perform authorization on your resource before an action.
|
@@ -544,13 +576,13 @@ Callbacks can also be defined for `JSONAPI::OperationsProcessor` events:
|
|
544
576
|
- `:remove_has_one_association_operation`: A `remove_has_one_association_operation`.
|
545
577
|
|
546
578
|
The operation callbacks have access to two meta data hashes, `@operations_meta` and `@operation_meta`, two links hashes,
|
547
|
-
`@operations_links` and `@operation_links`, the full list of `@operations`, each individual `@operation` and the
|
579
|
+
`@operations_links` and `@operation_links`, the full list of `@operations`, each individual `@operation` and the
|
548
580
|
`@result` variables.
|
549
581
|
|
550
582
|
##### Custom `OperationsProcessor` Example to Return total_count in Meta
|
551
583
|
|
552
584
|
Note: this can also be accomplished with the `top_level_meta_include_record_count` option, and in most cases that will
|
553
|
-
be the better option.
|
585
|
+
be the better option.
|
554
586
|
|
555
587
|
To return the total record count of a find operation in the meta data of a find operation you can create a custom
|
556
588
|
OperationsProcessor. For example:
|
@@ -565,14 +597,14 @@ end
|
|
565
597
|
|
566
598
|
Set the configuration option `operations_processor` to use the new `CountingActiveRecordOperationsProcessor` by
|
567
599
|
specifying the snake cased name of the class (without the `OperationsProcessor`).
|
568
|
-
|
600
|
+
|
569
601
|
```ruby
|
570
602
|
JSONAPI.configure do |config|
|
571
603
|
config.operations_processor = :counting_active_record
|
572
604
|
end
|
573
605
|
```
|
574
606
|
|
575
|
-
The callback code will be called after each find. It will use the same options as the find operation, without the
|
607
|
+
The callback code will be called after each find. It will use the same options as the find operation, without the
|
576
608
|
pagination, to collect the record count. This is stored in the `operation_meta`, which will be returned in the top level
|
577
609
|
meta element.
|
578
610
|
|
@@ -583,8 +615,8 @@ the `ActsAsResourceController` module.
|
|
583
615
|
|
584
616
|
##### ResourceController
|
585
617
|
|
586
|
-
`JSONAPI::Resources` provides a class, `ResourceController`, that can be used as the base class for your controllers.
|
587
|
-
`ResourceController` supports `index`, `show`, `create`, `update`, and `destroy` methods. Just deriving your controller
|
618
|
+
`JSONAPI::Resources` provides a class, `ResourceController`, that can be used as the base class for your controllers.
|
619
|
+
`ResourceController` supports `index`, `show`, `create`, `update`, and `destroy` methods. Just deriving your controller
|
588
620
|
from `ResourceController` will give you a fully functional controller.
|
589
621
|
|
590
622
|
For example:
|
@@ -634,7 +666,7 @@ JSONAPI::Resources supports namespacing of controllers and resources. With names
|
|
634
666
|
|
635
667
|
If you namespace your controller it will require a namespaced resource.
|
636
668
|
|
637
|
-
In the following example we have a `resource` that isn't namespaced, and one the has now been namespaced. There are
|
669
|
+
In the following example we have a `resource` that isn't namespaced, and one the has now been namespaced. There are
|
638
670
|
slight differences between the two resources, as might be seen in a new version of an API:
|
639
671
|
|
640
672
|
```ruby
|
@@ -793,14 +825,14 @@ This returns results like this:
|
|
793
825
|
"relationships": {
|
794
826
|
"section": {
|
795
827
|
"links": {
|
796
|
-
"self": "http://example.com/posts/1/
|
828
|
+
"self": "http://example.com/posts/1/relationships/section",
|
797
829
|
"related": "http://example.com/posts/1/section"
|
798
830
|
},
|
799
831
|
"data": null
|
800
832
|
},
|
801
833
|
"author": {
|
802
834
|
"links": {
|
803
|
-
"self": "http://example.com/posts/1/
|
835
|
+
"self": "http://example.com/posts/1/relationships/author",
|
804
836
|
"related": "http://example.com/posts/1/author"
|
805
837
|
},
|
806
838
|
"data": {
|
@@ -810,13 +842,13 @@ This returns results like this:
|
|
810
842
|
},
|
811
843
|
"tags": {
|
812
844
|
"links": {
|
813
|
-
"self": "http://example.com/posts/1/
|
845
|
+
"self": "http://example.com/posts/1/relationships/tags",
|
814
846
|
"related": "http://example.com/posts/1/tags"
|
815
847
|
}
|
816
848
|
},
|
817
849
|
"comments": {
|
818
850
|
"links": {
|
819
|
-
"self": "http://example.com/posts/1/
|
851
|
+
"self": "http://example.com/posts/1/relationships/comments",
|
820
852
|
"related": "http://example.com/posts/1/comments"
|
821
853
|
}
|
822
854
|
}
|
@@ -841,7 +873,7 @@ An array of resources. Nested resources can be specified with dot notation.
|
|
841
873
|
|
842
874
|
A hash of resource types and arrays of fields for each resource type.
|
843
875
|
|
844
|
-
*Purpose*: determines which fields are serialized for a resource type. This encompasses both attributes and
|
876
|
+
*Purpose*: determines which fields are serialized for a resource type. This encompasses both attributes and
|
845
877
|
association ids in the links section for a resource. Fields are global for a resource type.
|
846
878
|
|
847
879
|
*Example*: ```fields: { people: [:email, :comments], posts: [:title, :author], comments: [:body, :post]}```
|
@@ -936,7 +968,7 @@ gives routes that are only related to the primary resource, and none for its rel
|
|
936
968
|
```
|
937
969
|
|
938
970
|
To manually add in the nested routes you can use the `jsonapi_links`, `jsonapi_related_resources` and
|
939
|
-
`jsonapi_related_resource` inside the block. Or, you can add the default set of nested routes using the
|
971
|
+
`jsonapi_related_resource` inside the block. Or, you can add the default set of nested routes using the
|
940
972
|
`jsonapi_relationships` method. For example:
|
941
973
|
|
942
974
|
```ruby
|
@@ -1033,11 +1065,11 @@ phone_number_contact GET /phone-numbers/:phone_number_id/contact(.:format) co
|
|
1033
1065
|
|
1034
1066
|
#### Formatting
|
1035
1067
|
|
1036
|
-
JR by default uses some simple rules to format an attribute for serialization. Strings and Integers are output to JSON
|
1037
|
-
as is, and all other values have `.to_s` applied to them. This outputs something in all cases, but it is certainly not
|
1068
|
+
JR by default uses some simple rules to format an attribute for serialization. Strings and Integers are output to JSON
|
1069
|
+
as is, and all other values have `.to_s` applied to them. This outputs something in all cases, but it is certainly not
|
1038
1070
|
correct for every situation.
|
1039
1071
|
|
1040
|
-
If you want to change the way an attribute is serialized you have a couple of ways. The simplest method is to create a
|
1072
|
+
If you want to change the way an attribute is serialized you have a couple of ways. The simplest method is to create a
|
1041
1073
|
getter method on the resource which overrides the attribute and apply the formatting there. For example:
|
1042
1074
|
|
1043
1075
|
```ruby
|
@@ -1051,13 +1083,13 @@ class PersonResource < JSONAPI::Resource
|
|
1051
1083
|
end
|
1052
1084
|
```
|
1053
1085
|
|
1054
|
-
This is simple to implement for a one off situation, but not for example if you want to apply the same formatting rules
|
1055
|
-
to all DateTime fields in your system. Another issue is the attribute on the resource will always return a formatted
|
1086
|
+
This is simple to implement for a one off situation, but not for example if you want to apply the same formatting rules
|
1087
|
+
to all DateTime fields in your system. Another issue is the attribute on the resource will always return a formatted
|
1056
1088
|
response, whether you want it or not.
|
1057
1089
|
|
1058
1090
|
##### Value Formatters
|
1059
1091
|
|
1060
|
-
To overcome the above limitations JR uses Value Formatters. Value Formatters allow you to control the way values are
|
1092
|
+
To overcome the above limitations JR uses Value Formatters. Value Formatters allow you to control the way values are
|
1061
1093
|
handled for an attribute. The `format` can be set per attribute as it is declared in the resource. For example:
|
1062
1094
|
|
1063
1095
|
```ruby
|
@@ -1067,7 +1099,7 @@ class PersonResource < JSONAPI::Resource
|
|
1067
1099
|
end
|
1068
1100
|
```
|
1069
1101
|
|
1070
|
-
A Value formatter has a `format` and an `unformat` method. Here's the base ValueFormatter and DefaultValueFormatter for
|
1102
|
+
A Value formatter has a `format` and an `unformat` method. Here's the base ValueFormatter and DefaultValueFormatter for
|
1071
1103
|
reference:
|
1072
1104
|
|
1073
1105
|
```ruby
|
@@ -1100,21 +1132,21 @@ class DefaultValueFormatter < JSONAPI::ValueFormatter
|
|
1100
1132
|
end
|
1101
1133
|
```
|
1102
1134
|
|
1103
|
-
You can also create your own Value Formatter. Value Formatters must be named with the `format` name followed by
|
1135
|
+
You can also create your own Value Formatter. Value Formatters must be named with the `format` name followed by
|
1104
1136
|
`ValueFormatter`, i.e. `DateWithUTCTimezoneValueFormatter` and derive from `JSONAPI::ValueFormatter`. It is
|
1105
1137
|
recommended that you create a directory for your formatters, called `formatters`.
|
1106
1138
|
|
1107
|
-
The `format` method is called by the `ResourceSerializer` as is serializing a resource. The format method takes the
|
1139
|
+
The `format` method is called by the `ResourceSerializer` as is serializing a resource. The format method takes the
|
1108
1140
|
`raw_value` parameter. `raw_value` is the value as read from the model.
|
1109
1141
|
|
1110
|
-
The `unformat` method is called when processing the request. Each incoming attribute (except `links`) are run through
|
1111
|
-
the `unformat` method. The `unformat` method takes a `value`, which is the value as it comes in on the
|
1142
|
+
The `unformat` method is called when processing the request. Each incoming attribute (except `links`) are run through
|
1143
|
+
the `unformat` method. The `unformat` method takes a `value`, which is the value as it comes in on the
|
1112
1144
|
request. This allows you process the incoming value to alter its state before it is stored in the model.
|
1113
1145
|
|
1114
1146
|
###### Use a Different Default Value Formatter
|
1115
1147
|
|
1116
|
-
Another way to handle formatting is to set a different default value formatter. This will affect all attributes that do
|
1117
|
-
not have a `format` set. You can do this by overriding the `default_attribute_options` method for a resource (or a base
|
1148
|
+
Another way to handle formatting is to set a different default value formatter. This will affect all attributes that do
|
1149
|
+
not have a `format` set. You can do this by overriding the `default_attribute_options` method for a resource (or a base
|
1118
1150
|
resource for a system wide change).
|
1119
1151
|
|
1120
1152
|
```ruby
|
@@ -1146,11 +1178,11 @@ This way all DateTime values will be formatted to display in the UTC timezone.
|
|
1146
1178
|
|
1147
1179
|
#### Key Format
|
1148
1180
|
|
1149
|
-
By default JR uses dasherized keys as per the
|
1150
|
-
[JSON API naming recommendations](http://jsonapi.org/recommendations/#naming). This can be changed by specifying a
|
1181
|
+
By default JR uses dasherized keys as per the
|
1182
|
+
[JSON API naming recommendations](http://jsonapi.org/recommendations/#naming). This can be changed by specifying a
|
1151
1183
|
different key formatter.
|
1152
1184
|
|
1153
|
-
For example, to use camel cased keys with an initial lowercase character (JSON's default) create an initializer and add
|
1185
|
+
For example, to use camel cased keys with an initial lowercase character (JSON's default) create an initializer and add
|
1154
1186
|
the following:
|
1155
1187
|
|
1156
1188
|
```ruby
|
@@ -1160,7 +1192,7 @@ JSONAPI.configure do |config|
|
|
1160
1192
|
end
|
1161
1193
|
```
|
1162
1194
|
|
1163
|
-
This will cause the serializer to use the `CamelizedKeyFormatter`. You can also create your own `KeyFormatter`, for
|
1195
|
+
This will cause the serializer to use the `CamelizedKeyFormatter`. You can also create your own `KeyFormatter`, for
|
1164
1196
|
example:
|
1165
1197
|
|
1166
1198
|
```ruby
|
@@ -1177,7 +1209,7 @@ You would specify this in `JSONAPI.configure` as `:upper_camelized`.
|
|
1177
1209
|
|
1178
1210
|
## Configuration
|
1179
1211
|
|
1180
|
-
JR has a few configuration options. Some have already been mentioned above. To set configuration options create an
|
1212
|
+
JR has a few configuration options. Some have already been mentioned above. To set configuration options create an
|
1181
1213
|
initializer and add the options you wish to set. All options have defaults, so you only need to set the options that
|
1182
1214
|
are different. The default options are shown below.
|
1183
1215
|
|