jsonapi-resources 0.7.1.beta1 → 0.7.1.beta2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +248 -74
- data/lib/jsonapi-resources.rb +5 -3
- data/lib/jsonapi/acts_as_resource_controller.rb +77 -14
- data/lib/jsonapi/configuration.rb +77 -16
- data/lib/jsonapi/error.rb +12 -0
- data/lib/jsonapi/error_codes.rb +2 -0
- data/lib/jsonapi/exceptions.rb +29 -9
- data/lib/jsonapi/formatter.rb +29 -4
- data/lib/jsonapi/link_builder.rb +18 -18
- data/lib/jsonapi/mime_types.rb +25 -6
- data/lib/jsonapi/naive_cache.rb +30 -0
- data/lib/jsonapi/operation.rb +10 -342
- data/lib/jsonapi/operation_dispatcher.rb +87 -0
- data/lib/jsonapi/operation_result.rb +2 -1
- data/lib/jsonapi/paginator.rb +6 -2
- data/lib/jsonapi/processor.rb +283 -0
- data/lib/jsonapi/relationship.rb +6 -4
- data/lib/jsonapi/{request.rb → request_parser.rb} +46 -35
- data/lib/jsonapi/resource.rb +88 -13
- data/lib/jsonapi/resource_controller.rb +2 -14
- data/lib/jsonapi/resource_controller_metal.rb +17 -0
- data/lib/jsonapi/resource_serializer.rb +62 -47
- data/lib/jsonapi/resources/version.rb +1 -1
- data/lib/jsonapi/response_document.rb +13 -2
- data/lib/jsonapi/routing_ext.rb +49 -11
- metadata +37 -129
- data/.gitignore +0 -22
- data/.travis.yml +0 -9
- data/Gemfile +0 -23
- data/Rakefile +0 -20
- data/jsonapi-resources.gemspec +0 -29
- data/lib/jsonapi/active_record_operations_processor.rb +0 -35
- data/lib/jsonapi/operations_processor.rb +0 -120
- data/locales/en.yml +0 -80
- data/test/config/database.yml +0 -5
- data/test/controllers/controller_test.rb +0 -3312
- data/test/fixtures/active_record.rb +0 -1486
- data/test/fixtures/author_details.yml +0 -9
- data/test/fixtures/book_authors.yml +0 -3
- data/test/fixtures/book_comments.yml +0 -12
- data/test/fixtures/books.yml +0 -7
- data/test/fixtures/categories.yml +0 -35
- data/test/fixtures/comments.yml +0 -21
- data/test/fixtures/comments_tags.yml +0 -20
- data/test/fixtures/companies.yml +0 -4
- data/test/fixtures/craters.yml +0 -9
- data/test/fixtures/customers.yml +0 -11
- data/test/fixtures/documents.yml +0 -3
- data/test/fixtures/expense_entries.yml +0 -13
- data/test/fixtures/facts.yml +0 -11
- data/test/fixtures/hair_cuts.yml +0 -3
- data/test/fixtures/iso_currencies.yml +0 -17
- data/test/fixtures/line_items.yml +0 -37
- data/test/fixtures/makes.yml +0 -2
- data/test/fixtures/moons.yml +0 -6
- data/test/fixtures/numeros_telefone.yml +0 -3
- data/test/fixtures/order_flags.yml +0 -7
- data/test/fixtures/people.yml +0 -31
- data/test/fixtures/pictures.yml +0 -15
- data/test/fixtures/planet_types.yml +0 -19
- data/test/fixtures/planets.yml +0 -47
- data/test/fixtures/posts.yml +0 -102
- data/test/fixtures/posts_tags.yml +0 -59
- data/test/fixtures/preferences.yml +0 -14
- data/test/fixtures/products.yml +0 -3
- data/test/fixtures/purchase_orders.yml +0 -23
- data/test/fixtures/sections.yml +0 -8
- data/test/fixtures/tags.yml +0 -39
- data/test/fixtures/vehicles.yml +0 -17
- data/test/fixtures/web_pages.yml +0 -3
- data/test/helpers/assertions.rb +0 -13
- data/test/helpers/functional_helpers.rb +0 -59
- data/test/helpers/value_matchers.rb +0 -60
- data/test/helpers/value_matchers_test.rb +0 -40
- data/test/integration/requests/namespaced_model_test.rb +0 -13
- data/test/integration/requests/request_test.rb +0 -932
- data/test/integration/routes/routes_test.rb +0 -218
- data/test/integration/sti_fields_test.rb +0 -18
- data/test/lib/generators/jsonapi/controller_generator_test.rb +0 -25
- data/test/lib/generators/jsonapi/resource_generator_test.rb +0 -30
- data/test/test_helper.rb +0 -342
- data/test/unit/formatters/dasherized_key_formatter_test.rb +0 -8
- data/test/unit/jsonapi_request/jsonapi_request_test.rb +0 -199
- data/test/unit/operation/operations_processor_test.rb +0 -528
- data/test/unit/pagination/offset_paginator_test.rb +0 -245
- data/test/unit/pagination/paged_paginator_test.rb +0 -242
- data/test/unit/resource/resource_test.rb +0 -560
- data/test/unit/serializer/include_directives_test.rb +0 -113
- data/test/unit/serializer/link_builder_test.rb +0 -244
- data/test/unit/serializer/polymorphic_serializer_test.rb +0 -383
- data/test/unit/serializer/response_document_test.rb +0 -61
- data/test/unit/serializer/serializer_test.rb +0 -1939
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dceb946bf28d998cd1db3e5fbf7b16756cf8de1a
|
4
|
+
data.tar.gz: 5b5da11044442fc0afd60f0cac50e655692535d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 72b316a3c84777e316599dd3dafc51da115ea7cd7af2ee4cbad8d391fe594543eb81b7efa7834e57f6540f6b7ccfcc137e6d5c38eaa0f59373af6605c3051894
|
7
|
+
data.tar.gz: f9a961dfe2c6472e37f82c31e6764df600628841b0c05e1f02e3451c2872be068f78fffef1e4ee25406a54d6699b7d2161ccac334de888b56a85ca1b27de56cc
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# JSONAPI::Resources [![Build Status](https://secure.travis-ci.org/cerebris/jsonapi-resources.svg?branch=master)](http://travis-ci.org/cerebris/jsonapi-resources) [![Code Climate](https://codeclimate.com/github/cerebris/jsonapi-resources/badges/gpa.svg)](https://codeclimate.com/github/cerebris/jsonapi-resources)
|
1
|
+
# JSONAPI::Resources [![Gem Version](https://badge.fury.io/rb/jsonapi-resources.svg)](https://badge.fury.io/rb/jsonapi-resources) [![Build Status](https://secure.travis-ci.org/cerebris/jsonapi-resources.svg?branch=master)](http://travis-ci.org/cerebris/jsonapi-resources) [![Code Climate](https://codeclimate.com/github/cerebris/jsonapi-resources/badges/gpa.svg)](https://codeclimate.com/github/cerebris/jsonapi-resources)
|
2
2
|
|
3
3
|
[![Join the chat at https://gitter.im/cerebris/jsonapi-resources](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/cerebris/jsonapi-resources?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
4
4
|
|
@@ -19,22 +19,30 @@ backed by ActiveRecord models or by custom objects.
|
|
19
19
|
* [Usage] (#usage)
|
20
20
|
* [Resources] (#resources)
|
21
21
|
* [JSONAPI::Resource] (#jsonapiresource)
|
22
|
+
* [Context] (#context)
|
22
23
|
* [Attributes] (#attributes)
|
23
24
|
* [Primary Key] (#primary-key)
|
24
25
|
* [Model Name] (#model-name)
|
26
|
+
* [Model Hints] (#model-hints)
|
25
27
|
* [Relationships] (#relationships)
|
26
28
|
* [Filters] (#filters)
|
27
29
|
* [Pagination] (#pagination)
|
28
30
|
* [Included relationships (side-loading resources)] (#included-relationships-side-loading-resources)
|
29
31
|
* [Resource meta] (#resource-meta)
|
32
|
+
* [Custom Links] (#custom-links)
|
30
33
|
* [Callbacks] (#callbacks)
|
31
34
|
* [Controllers] (#controllers)
|
32
35
|
* [Namespaces] (#namespaces)
|
33
36
|
* [Error Codes] (#error-codes)
|
34
37
|
* [Handling Exceptions] (#handling-exceptions)
|
35
38
|
* [Action Callbacks] (#action-callbacks)
|
39
|
+
* [Operation Processors] (#operation-processors)
|
36
40
|
* [Serializer] (#serializer)
|
41
|
+
* [Serializer options] (#serializer-options)
|
42
|
+
* [Formatting] (#formatting)
|
43
|
+
* [Key Format] (#key-format)
|
37
44
|
* [Routing] (#routing)
|
45
|
+
* [Nested Routes] (#nested-routes)
|
38
46
|
* [Configuration] (#configuration)
|
39
47
|
* [Contributing] (#contributing)
|
40
48
|
* [License] (#license)
|
@@ -69,8 +77,7 @@ Or install it yourself as:
|
|
69
77
|
Resources define the public interface to your API. A resource defines which attributes are exposed, as well as
|
70
78
|
relationships to other resources.
|
71
79
|
|
72
|
-
Resource definitions should by convention be placed in a directory under app named resources, `app/resources`. The
|
73
|
-
name should be the single underscored name of the model that backs the resource with `_resource.rb` appended. For example,
|
80
|
+
Resource definitions should by convention be placed in a directory under app named resources, `app/resources`. The file name should be the single underscored name of the model that backs the resource with `_resource.rb` appended. For example,
|
74
81
|
a `Contact` model's resource should have a class named `ContactResource` defined in a file named `contact_resource.rb`.
|
75
82
|
|
76
83
|
#### JSONAPI::Resource
|
@@ -152,6 +159,36 @@ In the above example vehicles are immutable. A call to `/vehicles` or `/vehicles
|
|
152
159
|
of either `car` or `boat`. But calls to PUT or POST a `car` must be made to `/cars`. The rails models backing the above
|
153
160
|
code use Single Table Inheritance.
|
154
161
|
|
162
|
+
#### Context
|
163
|
+
|
164
|
+
Sometimes you will want to access things such as the current logged in user (and other state only available within your controllers) from within your resource classes. To make this state available to a resource class you need to put it into the context hash - this can be done via a `context` method on one of your controllers or across all controllers using ApplicationController.
|
165
|
+
|
166
|
+
For example:
|
167
|
+
|
168
|
+
```ruby
|
169
|
+
class ApplicationController < JSONAPI::ResourceController
|
170
|
+
def context
|
171
|
+
{current_user: current_user}
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
# Specific resource controllers derive from ApplicationController
|
176
|
+
# and share its context
|
177
|
+
class PeopleController < ApplicationController
|
178
|
+
|
179
|
+
end
|
180
|
+
|
181
|
+
# Assuming you don't permit user_id (so the client won't assign a wrong user to own the object)
|
182
|
+
# you can ensure the current user is assigned the record by using the controller's context hash.
|
183
|
+
class PeopleResource < JSONAPI::Resource
|
184
|
+
before_save do
|
185
|
+
@model.user_id = context[:current_user].id if @model.new_record?
|
186
|
+
end
|
187
|
+
end
|
188
|
+
```
|
189
|
+
|
190
|
+
You can put things that affect serialization and resource configuration into the context.
|
191
|
+
|
155
192
|
#### Attributes
|
156
193
|
|
157
194
|
Any of a resource's attributes that are accessible must be explicitly declared. Single attributes can be declared using
|
@@ -185,6 +222,18 @@ class ContactResource < JSONAPI::Resource
|
|
185
222
|
end
|
186
223
|
```
|
187
224
|
|
225
|
+
##### Attribute Delegation
|
226
|
+
|
227
|
+
Normally resource attributes map to an attribute on the model of the same name. Using the `delegate` option allows a resource
|
228
|
+
attribute to map to a differently named model attribute. For example:
|
229
|
+
|
230
|
+
```ruby
|
231
|
+
class ContactResource < JSONAPI::Resource
|
232
|
+
attribute :name_first, delegate: :first_name
|
233
|
+
attribute :name_last, delegate: :last_name
|
234
|
+
end
|
235
|
+
```
|
236
|
+
|
188
237
|
##### Fetchable Attributes
|
189
238
|
|
190
239
|
By default all attributes are assumed to be fetchable. The list of fetchable attributes can be filtered by overriding
|
@@ -258,6 +307,32 @@ class PostResource < JSONAPI::Resource
|
|
258
307
|
end
|
259
308
|
```
|
260
309
|
|
310
|
+
JR also supports sorting primary resources by fields on relationships.
|
311
|
+
|
312
|
+
Here's an example of sorting books by the author name:
|
313
|
+
|
314
|
+
```ruby
|
315
|
+
class Book < ActiveRecord::Base
|
316
|
+
belongs_to :author
|
317
|
+
end
|
318
|
+
|
319
|
+
class Author < ActiveRecord::Base
|
320
|
+
has_many :books
|
321
|
+
end
|
322
|
+
|
323
|
+
class BookResource < JSONAPI::Resource
|
324
|
+
attributes :title, :body
|
325
|
+
|
326
|
+
def self.sortable_fields(context)
|
327
|
+
super(context) << :"author.name"
|
328
|
+
end
|
329
|
+
end
|
330
|
+
```
|
331
|
+
The request will look something like:
|
332
|
+
```
|
333
|
+
GET /books?include=author&sort=author.name
|
334
|
+
```
|
335
|
+
|
261
336
|
##### Attribute Formatting
|
262
337
|
|
263
338
|
Attributes can have a `Format`. By default all attributes use the default formatter. If an attribute has the `format`
|
@@ -670,7 +745,7 @@ default any other error that you raise will return a `500` status code
|
|
670
745
|
for a general internal server error.
|
671
746
|
|
672
747
|
To return useful error codes that represent application errors you
|
673
|
-
should set the `exception_class_whitelist` config
|
748
|
+
should set the `exception_class_whitelist` config variable, and then you
|
674
749
|
should use the Rails `rescue_from` macro to render a status code.
|
675
750
|
|
676
751
|
For example, this config setting allows the `NotAuthorizedError` to bubble up out of
|
@@ -785,12 +860,22 @@ The `paged` `paginator` returns results based on pages of a fixed size. Valid `p
|
|
785
860
|
If `number` is omitted the first page is returned. If `size` is omitted the `default_page_size` from the configuration
|
786
861
|
settings is used.
|
787
862
|
|
863
|
+
```
|
864
|
+
GET /articles?page%5Bnumber%5D=10&page%5Bsize%5D=10 HTTP/1.1
|
865
|
+
Accept: application/vnd.api+json
|
866
|
+
```
|
867
|
+
|
788
868
|
###### Offset Paginator
|
789
869
|
|
790
870
|
The `offset` `paginator` returns results based on an offset from the beginning of the resultset. Valid `page` parameters
|
791
871
|
are `offset` and `limit`. If `offset` is omitted a value of 0 will be used. If `limit` is omitted the `default_page_size`
|
792
872
|
from the configuration settings is used.
|
793
873
|
|
874
|
+
```
|
875
|
+
GET /articles?page%5Blimit%5D=10&page%5Boffset%5D=10 HTTP/1.1
|
876
|
+
Accept: application/vnd.api+json
|
877
|
+
```
|
878
|
+
|
794
879
|
###### Custom Paginators
|
795
880
|
|
796
881
|
Custom `paginators` can be used. These should derive from `Paginator`. The `apply` method takes a `relation` and
|
@@ -914,7 +999,7 @@ class BookResource < JSONAPI::Resource
|
|
914
999
|
def meta(options)
|
915
1000
|
{
|
916
1001
|
copyright: 'API Copyright 2015 - XYZ Corp.',
|
917
|
-
computed_copyright: options[:serialization_options][:copyright]
|
1002
|
+
computed_copyright: options[:serialization_options][:copyright],
|
918
1003
|
last_updated_at: _model.updated_at
|
919
1004
|
}
|
920
1005
|
end
|
@@ -924,11 +1009,77 @@ end
|
|
924
1009
|
|
925
1010
|
The `meta` method will be called for each resource instance. Override the `meta` method on a resource class to control
|
926
1011
|
the meta information for the resource. If a non empty hash is returned from `meta` this will be serialized. The `meta`
|
927
|
-
method is called with an `options`
|
1012
|
+
method is called with an `options` hash. The `options` hash will contain the following:
|
1013
|
+
|
1014
|
+
* `:serializer` -> the serializer instance
|
1015
|
+
* `:serialization_options` -> the contents of the `serialization_options` method on the controller.
|
1016
|
+
|
1017
|
+
#### Custom Links
|
1018
|
+
|
1019
|
+
Custom links can be included for each resource by overriding the `custom_links` method. If a non empty hash is returned from `custom_links`, it will be merged with the default links hash containing the resource's `self` link. The `custom_links` method is called with the same `options` hash used by for [resource meta information](#resource-meta). The `options` hash contains the following:
|
928
1020
|
|
929
1021
|
* `:serializer` -> the serializer instance
|
930
1022
|
* `:serialization_options` -> the contents of the `serialization_options` method on the controller.
|
931
1023
|
|
1024
|
+
For example:
|
1025
|
+
|
1026
|
+
```ruby
|
1027
|
+
class CityCouncilMeeting < JSONAPI::Resource
|
1028
|
+
attribute :title, :location, :approved
|
1029
|
+
|
1030
|
+
def custom_links(options)
|
1031
|
+
{ minutes: options[:serializer].link_builder.self_link(self) + "/minutes" }
|
1032
|
+
end
|
1033
|
+
end
|
1034
|
+
```
|
1035
|
+
|
1036
|
+
This will create a custom link with the key `minutes`, which will be merged with the default `self` link, like so:
|
1037
|
+
|
1038
|
+
```json
|
1039
|
+
{
|
1040
|
+
"data": [
|
1041
|
+
{
|
1042
|
+
"id": "1",
|
1043
|
+
"type": "cityCouncilMeetings",
|
1044
|
+
"links": {
|
1045
|
+
"self": "http://city.gov/api/city-council-meetings/1",
|
1046
|
+
"minutes": "http://city.gov/api/city-council-meetings/1/minutes"
|
1047
|
+
},
|
1048
|
+
"attributes": {...}
|
1049
|
+
},
|
1050
|
+
//...
|
1051
|
+
]
|
1052
|
+
}
|
1053
|
+
```
|
1054
|
+
|
1055
|
+
Of course, the `custom_links` method can include logic to include links only when relevant:
|
1056
|
+
|
1057
|
+
````ruby
|
1058
|
+
class CityCouncilMeeting < JSONAPI::Resource
|
1059
|
+
attribute :title, :location, :approved
|
1060
|
+
|
1061
|
+
delegate :approved?, to: :model
|
1062
|
+
|
1063
|
+
def custom_links(options)
|
1064
|
+
extra_links = {}
|
1065
|
+
if approved?
|
1066
|
+
extra_links[:minutes] = options[:serializer].link_builder.self_link(self) + "/minutes"
|
1067
|
+
end
|
1068
|
+
extra_links
|
1069
|
+
end
|
1070
|
+
end
|
1071
|
+
```
|
1072
|
+
|
1073
|
+
It's also possibly to suppress the default `self` link by returning a hash with `{self: nil}`:
|
1074
|
+
|
1075
|
+
````ruby
|
1076
|
+
class Selfless < JSONAPI::Resource
|
1077
|
+
def custom_links(options)
|
1078
|
+
{self: nil}
|
1079
|
+
end
|
1080
|
+
end
|
1081
|
+
```
|
1082
|
+
|
932
1083
|
#### Callbacks
|
933
1084
|
|
934
1085
|
`ActiveSupport::Callbacks` is used to provide callback functionality, so the behavior is very similar to what you may be
|
@@ -967,60 +1118,31 @@ Callbacks can be defined for the following `JSONAPI::Resource` events:
|
|
967
1118
|
- `:remove_to_one_link`
|
968
1119
|
- `:replace_fields`
|
969
1120
|
|
970
|
-
##### `JSONAPI::
|
1121
|
+
##### `JSONAPI::Processor` Callbacks
|
971
1122
|
|
972
|
-
Callbacks can also be defined for `JSONAPI::
|
973
|
-
- `:operations`: The set of operations.
|
1123
|
+
Callbacks can also be defined for `JSONAPI::Processor` events:
|
974
1124
|
- `:operation`: Any individual operation.
|
975
|
-
- `:
|
976
|
-
- `:
|
977
|
-
- `:
|
978
|
-
- `:
|
979
|
-
- `:
|
980
|
-
- `:
|
981
|
-
- `:
|
982
|
-
- `:
|
983
|
-
- `:
|
984
|
-
- `:
|
985
|
-
- `:
|
986
|
-
- `:
|
987
|
-
- `:
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
be the better option.
|
997
|
-
|
998
|
-
To return the total record count of a find operation in the meta data of a find operation you can create a custom
|
999
|
-
OperationsProcessor. For example:
|
1000
|
-
|
1001
|
-
```ruby
|
1002
|
-
# lib/jsonapi/counting_active_record_operations_processor.rb
|
1003
|
-
class CountingActiveRecordOperationsProcessor < ActiveRecordOperationsProcessor
|
1004
|
-
after_find_operation do
|
1005
|
-
@operation_meta[:total_records] = @operation.record_count
|
1006
|
-
end
|
1007
|
-
end
|
1008
|
-
```
|
1009
|
-
|
1010
|
-
Set the configuration option `operations_processor` to use the new `CountingActiveRecordOperationsProcessor` by
|
1011
|
-
specifying the snake cased name of the class (without the `OperationsProcessor`).
|
1012
|
-
|
1013
|
-
```ruby
|
1014
|
-
require 'jsonapi/counting_active_record_operations_processor'
|
1015
|
-
|
1016
|
-
JSONAPI.configure do |config|
|
1017
|
-
config.operations_processor = :counting_active_record
|
1018
|
-
end
|
1019
|
-
```
|
1020
|
-
|
1021
|
-
The callback code will be called after each find. It will use the same options as the find operation, without the
|
1022
|
-
pagination, to collect the record count. This is stored in the `operation_meta`, which will be returned in the top level
|
1023
|
-
meta element.
|
1125
|
+
- `:find`: A `find` operation is being processed.
|
1126
|
+
- `:show`: A `show` operation is being processed.
|
1127
|
+
- `:show_relationship`: A `show_relationship` operation is being processed.
|
1128
|
+
- `:show_related_resource`: A `show_related_resource` operation is being processed.
|
1129
|
+
- `:show_related_resources`: A `show_related_resources` operation is being processed.
|
1130
|
+
- `:create_resource`: A `create_resource` operation is being processed.
|
1131
|
+
- `:remove_resource`: A `remove_resource` operation is being processed.
|
1132
|
+
- `:replace_fields`: A `replace_fields` operation is being processed.
|
1133
|
+
- `:replace_to_one_relationship`: A `replace_to_one_relationship` operation is being processed.
|
1134
|
+
- `:create_to_many_relationship`: A `create_to_many_relationship` operation is being processed.
|
1135
|
+
- `:replace_to_many_relationship`: A `replace_to_many_relationship` operation is being processed.
|
1136
|
+
- `:remove_to_many_relationship`: A `remove_to_many_relationship` operation is being processed.
|
1137
|
+
- `:remove_to_one_relationship`: A `remove_to_one_relationship` operation is being processed.
|
1138
|
+
|
1139
|
+
See [Operation Processors] (#operation-processors) for details on using OperationProcessors
|
1140
|
+
|
1141
|
+
##### `JSONAPI::OperationsProcessor` Callbacks (a removed feature)
|
1142
|
+
|
1143
|
+
Note: The `JSONAPI::OperationsProcessor` has been removed and replaced with the `JSONAPI::OperationDispatcher`
|
1144
|
+
and `Processor` classes per resource. The callbacks have been renamed and moved to the
|
1145
|
+
`Processor`s, with the exception of the `operations` callback which is now on the controller.
|
1024
1146
|
|
1025
1147
|
### Controllers
|
1026
1148
|
|
@@ -1044,30 +1166,27 @@ end
|
|
1044
1166
|
Of course you are free to extend this as needed and override action handlers or other methods.
|
1045
1167
|
|
1046
1168
|
A jsonapi-controller generator is avaliable
|
1169
|
+
|
1047
1170
|
```
|
1048
1171
|
rails generate jsonapi:controller contact
|
1049
1172
|
```
|
1050
1173
|
|
1051
|
-
######
|
1174
|
+
###### ResourceControllerMetal
|
1052
1175
|
|
1053
|
-
|
1176
|
+
`JSONAPI::Resources` also provides an alternative class to `ResourceController` called `ResourceControllerMetal`.
|
1177
|
+
In order to provide a lighter weight controller option this strips the controller down to just the classes needed
|
1178
|
+
to work with `JSONAPI::Resources`.
|
1054
1179
|
|
1055
1180
|
For example:
|
1056
1181
|
|
1057
1182
|
```ruby
|
1058
|
-
class
|
1059
|
-
def context
|
1060
|
-
{current_user: current_user}
|
1061
|
-
end
|
1062
|
-
end
|
1063
|
-
|
1064
|
-
# Specific resource controllers derive from ApplicationController
|
1065
|
-
# and share its context
|
1066
|
-
class PeopleController < ApplicationController
|
1183
|
+
class PeopleController < JSONAPI::ResourceControllerMetal
|
1067
1184
|
|
1068
1185
|
end
|
1069
1186
|
```
|
1070
1187
|
|
1188
|
+
Note: This may not provide all of the expected controller capabilities if you are using additional gems such as DoorKeeper.
|
1189
|
+
|
1071
1190
|
###### Serialization Options
|
1072
1191
|
|
1073
1192
|
Additional options can be passed to the serializer using the `serialization_options` method.
|
@@ -1217,6 +1336,7 @@ module JSONAPI
|
|
1217
1336
|
SAVE_FAILED = '121'
|
1218
1337
|
FORBIDDEN = '403'
|
1219
1338
|
RECORD_NOT_FOUND = '404'
|
1339
|
+
NOT_ACCEPTABLE = '406'
|
1220
1340
|
UNSUPPORTED_MEDIA_TYPE = '415'
|
1221
1341
|
LOCKED = '423'
|
1222
1342
|
end
|
@@ -1278,6 +1398,56 @@ class UsersController < JSONAPI::ResourceController
|
|
1278
1398
|
end
|
1279
1399
|
```
|
1280
1400
|
|
1401
|
+
### Operation Processors
|
1402
|
+
|
1403
|
+
Operation Processors are called to perform the operation(s) that make up a request. The controller (through the `OperationDispatcher`), creates an `OperatorProcessor` to handle each operation. The processor is created based on the resource name, including the namespace. If a processor does not exist for a resource (namespace matters) the default operation processor is used instead. The default processor can be changed by a configuration setting.
|
1404
|
+
|
1405
|
+
Defining a custom `Processor` allows for custom callback handling of each operation type for each resource type. For example:
|
1406
|
+
|
1407
|
+
```ruby
|
1408
|
+
class Api::V4::BookProcessor < JSONAPI::Processor
|
1409
|
+
after_find do
|
1410
|
+
unless @result.is_a?(JSONAPI::ErrorsOperationResult)
|
1411
|
+
@result.meta[:total_records_found] = @result.record_count
|
1412
|
+
end
|
1413
|
+
end
|
1414
|
+
end
|
1415
|
+
```
|
1416
|
+
|
1417
|
+
This simple example uses a callback to update the result's meta property with the total count of records (a redundant
|
1418
|
+
feature only for example purposes), if there wasn't an error in the operation. It is also possible to override the
|
1419
|
+
`find` method as well if a different behavior is needed, for example:
|
1420
|
+
|
1421
|
+
```ruby
|
1422
|
+
class Api::V4::BookProcessor < JSONAPI::Processor
|
1423
|
+
def find
|
1424
|
+
filters = params[:filters]
|
1425
|
+
include_directives = params[:include_directives]
|
1426
|
+
sort_criteria = params.fetch(:sort_criteria, [])
|
1427
|
+
paginator = params[:paginator]
|
1428
|
+
|
1429
|
+
verified_filters = resource_klass.verify_filters(filters, context)
|
1430
|
+
resource_records = resource_klass.find(verified_filters,
|
1431
|
+
context: context,
|
1432
|
+
include_directives: include_directives,
|
1433
|
+
sort_criteria: sort_criteria,
|
1434
|
+
paginator: paginator)
|
1435
|
+
|
1436
|
+
page_options = {}
|
1437
|
+
# Overriding the default record count logic to always include it in the meta
|
1438
|
+
#if (JSONAPI.configuration.top_level_meta_include_record_count ||
|
1439
|
+
# (paginator && paginator.class.requires_record_count))
|
1440
|
+
page_options[:record_count] = resource_klass.find_count(verified_filters,
|
1441
|
+
context: context,
|
1442
|
+
include_directives: include_directives)
|
1443
|
+
#end
|
1444
|
+
end
|
1445
|
+
```
|
1446
|
+
|
1447
|
+
Note: The authors of this gem expect the most common uses cases to be handled using the callbacks. It is likely that the
|
1448
|
+
internal functionality of the operation processing methods will change, at least for several revisions. Effort will be
|
1449
|
+
made to call this out in release notes. You have been warned.
|
1450
|
+
|
1281
1451
|
### Serializer
|
1282
1452
|
|
1283
1453
|
The `ResourceSerializer` can be used to serialize a resource into JSON API compliant JSON. `ResourceSerializer` must be
|
@@ -1698,8 +1868,7 @@ JR has a few configuration options. Some have already been mentioned above. To s
|
|
1698
1868
|
initializer and add the options you wish to set. All options have defaults, so you only need to set the options that
|
1699
1869
|
are different. The default options are shown below.
|
1700
1870
|
|
1701
|
-
If using custom classes (such as
|
1702
|
-
be sure to require them at the top of the initializer before usage.
|
1871
|
+
If using custom classes (such as a CustomPaginator), be sure to require them at the top of the initializer before usage.
|
1703
1872
|
|
1704
1873
|
```ruby
|
1705
1874
|
JSONAPI.configure do |config|
|
@@ -1709,8 +1878,9 @@ JSONAPI.configure do |config|
|
|
1709
1878
|
#:underscored_route, :camelized_route, :dasherized_route, or custom
|
1710
1879
|
config.route_format = :dasherized_route
|
1711
1880
|
|
1712
|
-
|
1713
|
-
|
1881
|
+
# Default Processor, used if a resource specific one is not defined.
|
1882
|
+
# Must be a class
|
1883
|
+
config.default_processor_klass = JSONAPI::Processor
|
1714
1884
|
|
1715
1885
|
#:integer, :uuid, :string, or custom (provide a proc)
|
1716
1886
|
config.resource_key_type = :integer
|
@@ -1739,6 +1909,10 @@ JSONAPI.configure do |config|
|
|
1739
1909
|
config.top_level_meta_include_record_count = false
|
1740
1910
|
config.top_level_meta_record_count_key = :record_count
|
1741
1911
|
|
1912
|
+
# For :paged paginators, the following are also available
|
1913
|
+
config.top_level_meta_include_page_count = false
|
1914
|
+
config.top_level_meta_page_count_key = :page_count
|
1915
|
+
|
1742
1916
|
config.use_text_errors = false
|
1743
1917
|
|
1744
1918
|
# List of classes that should not be rescued by the operations processor.
|
@@ -1767,4 +1941,4 @@ end
|
|
1767
1941
|
|
1768
1942
|
## License
|
1769
1943
|
|
1770
|
-
Copyright 2014 Cerebris Corporation. MIT License (see LICENSE for details).
|
1944
|
+
Copyright 2014-2016 Cerebris Corporation. MIT License (see LICENSE for details).
|