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.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +248 -74
  3. data/lib/jsonapi-resources.rb +5 -3
  4. data/lib/jsonapi/acts_as_resource_controller.rb +77 -14
  5. data/lib/jsonapi/configuration.rb +77 -16
  6. data/lib/jsonapi/error.rb +12 -0
  7. data/lib/jsonapi/error_codes.rb +2 -0
  8. data/lib/jsonapi/exceptions.rb +29 -9
  9. data/lib/jsonapi/formatter.rb +29 -4
  10. data/lib/jsonapi/link_builder.rb +18 -18
  11. data/lib/jsonapi/mime_types.rb +25 -6
  12. data/lib/jsonapi/naive_cache.rb +30 -0
  13. data/lib/jsonapi/operation.rb +10 -342
  14. data/lib/jsonapi/operation_dispatcher.rb +87 -0
  15. data/lib/jsonapi/operation_result.rb +2 -1
  16. data/lib/jsonapi/paginator.rb +6 -2
  17. data/lib/jsonapi/processor.rb +283 -0
  18. data/lib/jsonapi/relationship.rb +6 -4
  19. data/lib/jsonapi/{request.rb → request_parser.rb} +46 -35
  20. data/lib/jsonapi/resource.rb +88 -13
  21. data/lib/jsonapi/resource_controller.rb +2 -14
  22. data/lib/jsonapi/resource_controller_metal.rb +17 -0
  23. data/lib/jsonapi/resource_serializer.rb +62 -47
  24. data/lib/jsonapi/resources/version.rb +1 -1
  25. data/lib/jsonapi/response_document.rb +13 -2
  26. data/lib/jsonapi/routing_ext.rb +49 -11
  27. metadata +37 -129
  28. data/.gitignore +0 -22
  29. data/.travis.yml +0 -9
  30. data/Gemfile +0 -23
  31. data/Rakefile +0 -20
  32. data/jsonapi-resources.gemspec +0 -29
  33. data/lib/jsonapi/active_record_operations_processor.rb +0 -35
  34. data/lib/jsonapi/operations_processor.rb +0 -120
  35. data/locales/en.yml +0 -80
  36. data/test/config/database.yml +0 -5
  37. data/test/controllers/controller_test.rb +0 -3312
  38. data/test/fixtures/active_record.rb +0 -1486
  39. data/test/fixtures/author_details.yml +0 -9
  40. data/test/fixtures/book_authors.yml +0 -3
  41. data/test/fixtures/book_comments.yml +0 -12
  42. data/test/fixtures/books.yml +0 -7
  43. data/test/fixtures/categories.yml +0 -35
  44. data/test/fixtures/comments.yml +0 -21
  45. data/test/fixtures/comments_tags.yml +0 -20
  46. data/test/fixtures/companies.yml +0 -4
  47. data/test/fixtures/craters.yml +0 -9
  48. data/test/fixtures/customers.yml +0 -11
  49. data/test/fixtures/documents.yml +0 -3
  50. data/test/fixtures/expense_entries.yml +0 -13
  51. data/test/fixtures/facts.yml +0 -11
  52. data/test/fixtures/hair_cuts.yml +0 -3
  53. data/test/fixtures/iso_currencies.yml +0 -17
  54. data/test/fixtures/line_items.yml +0 -37
  55. data/test/fixtures/makes.yml +0 -2
  56. data/test/fixtures/moons.yml +0 -6
  57. data/test/fixtures/numeros_telefone.yml +0 -3
  58. data/test/fixtures/order_flags.yml +0 -7
  59. data/test/fixtures/people.yml +0 -31
  60. data/test/fixtures/pictures.yml +0 -15
  61. data/test/fixtures/planet_types.yml +0 -19
  62. data/test/fixtures/planets.yml +0 -47
  63. data/test/fixtures/posts.yml +0 -102
  64. data/test/fixtures/posts_tags.yml +0 -59
  65. data/test/fixtures/preferences.yml +0 -14
  66. data/test/fixtures/products.yml +0 -3
  67. data/test/fixtures/purchase_orders.yml +0 -23
  68. data/test/fixtures/sections.yml +0 -8
  69. data/test/fixtures/tags.yml +0 -39
  70. data/test/fixtures/vehicles.yml +0 -17
  71. data/test/fixtures/web_pages.yml +0 -3
  72. data/test/helpers/assertions.rb +0 -13
  73. data/test/helpers/functional_helpers.rb +0 -59
  74. data/test/helpers/value_matchers.rb +0 -60
  75. data/test/helpers/value_matchers_test.rb +0 -40
  76. data/test/integration/requests/namespaced_model_test.rb +0 -13
  77. data/test/integration/requests/request_test.rb +0 -932
  78. data/test/integration/routes/routes_test.rb +0 -218
  79. data/test/integration/sti_fields_test.rb +0 -18
  80. data/test/lib/generators/jsonapi/controller_generator_test.rb +0 -25
  81. data/test/lib/generators/jsonapi/resource_generator_test.rb +0 -30
  82. data/test/test_helper.rb +0 -342
  83. data/test/unit/formatters/dasherized_key_formatter_test.rb +0 -8
  84. data/test/unit/jsonapi_request/jsonapi_request_test.rb +0 -199
  85. data/test/unit/operation/operations_processor_test.rb +0 -528
  86. data/test/unit/pagination/offset_paginator_test.rb +0 -245
  87. data/test/unit/pagination/paged_paginator_test.rb +0 -242
  88. data/test/unit/resource/resource_test.rb +0 -560
  89. data/test/unit/serializer/include_directives_test.rb +0 -113
  90. data/test/unit/serializer/link_builder_test.rb +0 -244
  91. data/test/unit/serializer/polymorphic_serializer_test.rb +0 -383
  92. data/test/unit/serializer/response_document_test.rb +0 -61
  93. data/test/unit/serializer/serializer_test.rb +0 -1939
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cb58ea800ff6a685353e48ffca57603b1db612d8
4
- data.tar.gz: 542b9ec812a94328f50204bbbef8743d593c2413
3
+ metadata.gz: dceb946bf28d998cd1db3e5fbf7b16756cf8de1a
4
+ data.tar.gz: 5b5da11044442fc0afd60f0cac50e655692535d9
5
5
  SHA512:
6
- metadata.gz: f2ad634e949bce4a5a0f1482dbd66392e97efba3f015a3eb9c3c87b8fe0b7ed0b8bb5e1a2f6dcde3bd228ad64b51de2cd6d12aed9586980e4cadf5aeb59d6acd
7
- data.tar.gz: 7a4a9275358f79a011b2610e316cd5190beb23e375661ef0508fb65cd3c0b08c7d0bbf751ca0ef37d98a455f842e059feb5d39be70b70b63aa2dc53308bb24ae
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 class
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 varible, and then you
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` has. The `options` hash will contain the following:
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::OperationsProcessor` Callbacks
1121
+ ##### `JSONAPI::Processor` Callbacks
971
1122
 
972
- Callbacks can also be defined for `JSONAPI::OperationsProcessor` events:
973
- - `:operations`: The set of operations.
1123
+ Callbacks can also be defined for `JSONAPI::Processor` events:
974
1124
  - `:operation`: Any individual operation.
975
- - `:find_operation`: A `find_operation`.
976
- - `:show_operation`: A `show_operation`.
977
- - `:show_relationship_operation`: A `show_relationship_operation`.
978
- - `:show_related_resource_operation`: A `show_related_resource_operation`.
979
- - `:show_related_resources_operation`: A `show_related_resources_operation`.
980
- - `:create_resource_operation`: A `create_resource_operation`.
981
- - `:remove_resource_operation`: A `remove_resource_operation`.
982
- - `:replace_fields_operation`: A `replace_fields_operation`.
983
- - `:replace_to_one_relationship_operation`: A `replace_to_one_relationship_operation`.
984
- - `:create_to_many_relationship_operation`: A `create_to_many_relationship_operation`.
985
- - `:replace_to_many_relationship_operation`: A `replace_to_many_relationship_operation`.
986
- - `:remove_to_many_relationship_operation`: A `remove_to_many_relationship_operation`.
987
- - `:remove_to_one_relationship_operation`: A `remove_to_one_relationship_operation`.
988
-
989
- The operation callbacks have access to two meta data hashes, `@operations_meta` and `@operation_meta`, two links hashes,
990
- `@operations_links` and `@operation_links`, the full list of `@operations`, each individual `@operation` and the
991
- `@result` variables.
992
-
993
- ##### Custom `OperationsProcessor` Example to Return total_count in Meta
994
-
995
- Note: this can also be accomplished with the `top_level_meta_include_record_count` option, and in most cases that will
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
- ###### Context
1174
+ ###### ResourceControllerMetal
1052
1175
 
1053
- The context that's used for serialization and resource configuration is set by the controller's `context` method.
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 ApplicationController < JSONAPI::ResourceController
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 the CountingActiveRecordOperationsProcessor, or a CustomPaginator),
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
- #:basic, :active_record, or custom
1713
- config.operations_processor = :active_record
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).