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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -2
  3. data/README.md +103 -71
  4. data/Rakefile +2 -2
  5. data/jsonapi-resources.gemspec +2 -2
  6. data/lib/jsonapi-resources.rb +0 -1
  7. data/lib/jsonapi/active_record_operations_processor.rb +10 -2
  8. data/lib/jsonapi/acts_as_resource_controller.rb +26 -24
  9. data/lib/jsonapi/association.rb +50 -15
  10. data/lib/jsonapi/callbacks.rb +1 -2
  11. data/lib/jsonapi/configuration.rb +8 -24
  12. data/lib/jsonapi/error.rb +1 -2
  13. data/lib/jsonapi/error_codes.rb +3 -1
  14. data/lib/jsonapi/exceptions.rb +59 -47
  15. data/lib/jsonapi/include_directives.rb +11 -11
  16. data/lib/jsonapi/mime_types.rb +2 -2
  17. data/lib/jsonapi/operation.rb +28 -11
  18. data/lib/jsonapi/operations_processor.rb +16 -5
  19. data/lib/jsonapi/paginator.rb +19 -19
  20. data/lib/jsonapi/request.rb +175 -196
  21. data/lib/jsonapi/resource.rb +158 -105
  22. data/lib/jsonapi/resource_serializer.rb +37 -26
  23. data/lib/jsonapi/resources/version.rb +2 -2
  24. data/lib/jsonapi/response_document.rb +5 -4
  25. data/lib/jsonapi/routing_ext.rb +24 -19
  26. data/test/controllers/controller_test.rb +261 -31
  27. data/test/fixtures/active_record.rb +206 -8
  28. data/test/fixtures/book_comments.yml +2 -1
  29. data/test/fixtures/books.yml +1 -0
  30. data/test/fixtures/documents.yml +3 -0
  31. data/test/fixtures/people.yml +8 -1
  32. data/test/fixtures/pictures.yml +15 -0
  33. data/test/fixtures/products.yml +3 -0
  34. data/test/fixtures/vehicles.yml +8 -0
  35. data/test/helpers/{hash_helpers.rb → assertions.rb} +6 -1
  36. data/test/integration/requests/request_test.rb +14 -3
  37. data/test/integration/routes/routes_test.rb +47 -0
  38. data/test/test_helper.rb +27 -4
  39. data/test/unit/serializer/include_directives_test.rb +5 -0
  40. data/test/unit/serializer/polymorphic_serializer_test.rb +384 -0
  41. data/test/unit/serializer/serializer_test.rb +19 -1
  42. metadata +14 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ee2eb1bf17d93331630573c19708775eb1bb5379
4
- data.tar.gz: 0e230d825047eebc973ad2b3c16a10d47c0ee54a
3
+ metadata.gz: 797927f93aedcb2dab47c655c02b3b0fc585ae3a
4
+ data.tar.gz: 679a57fb31f8a64b19735130d70bd79eef9b46ad
5
5
  SHA512:
6
- metadata.gz: 7ef3d97d1b89d5ceb0e585eddc32c7b69dfd6e3b60b96f4eb401634d4a1f32e65e7f75d11baa3f1a5adc1c66e2aa4a729b18f014bb084a775e9300a9e3ae933f
7
- data.tar.gz: 7328baee52874231838085886f9d5280932c0f3950a93a9f001d9bdaf341c4a68000a1ae05700b60c7b429f283e53d6863f9bf7d811c9065aa4941a347f36197
6
+ metadata.gz: 39a597f4b31a1273f4a7a71bf3b46ea0a19251b235a2fb8212c3452d959c6b01094a33420bad1fc7ac69d1c082d8193cb99d7c73e5f541c747c60d3503de1190
7
+ data.tar.gz: 819a12d466c075c127b9a9c6863b675fd3dc28a21f011022132c460badeb8e102745aacfb9cc4c6cab4c60d4f69d41f9b22fbbe8c1804ad4b92c2c0a43006a54
data/Gemfile CHANGED
@@ -13,9 +13,9 @@ end
13
13
  version = ENV['RAILS_VERSION'] || 'default'
14
14
  rails = case version
15
15
  when 'master'
16
- {:github => 'rails/rails'}
16
+ { github: 'rails/rails' }
17
17
  when 'default'
18
- '>= 4.2'
18
+ '>= 4.2'
19
19
  else
20
20
  "~> #{version}"
21
21
  end
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
- class CommentResource < JSONAPI::Resource
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
- end
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/links/section",
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/links/author",
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/links/tags",
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/links/comments",
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