active_model_serializers_custom 0.10.90

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. checksums.yaml +7 -0
  2. data/.github/ISSUE_TEMPLATE.md +29 -0
  3. data/.github/PULL_REQUEST_TEMPLATE.md +15 -0
  4. data/.gitignore +35 -0
  5. data/.rubocop.yml +109 -0
  6. data/.simplecov +110 -0
  7. data/.travis.yml +63 -0
  8. data/CHANGELOG.md +727 -0
  9. data/CODE_OF_CONDUCT.md +74 -0
  10. data/CONTRIBUTING.md +105 -0
  11. data/Gemfile +74 -0
  12. data/MIT-LICENSE +22 -0
  13. data/README.md +305 -0
  14. data/Rakefile +76 -0
  15. data/active_model_serializers.gemspec +64 -0
  16. data/appveyor.yml +28 -0
  17. data/bin/bench +171 -0
  18. data/bin/bench_regression +316 -0
  19. data/bin/rubocop +38 -0
  20. data/bin/serve_benchmark +39 -0
  21. data/docs/README.md +41 -0
  22. data/docs/STYLE.md +58 -0
  23. data/docs/general/adapters.md +269 -0
  24. data/docs/general/caching.md +58 -0
  25. data/docs/general/configuration_options.md +185 -0
  26. data/docs/general/deserialization.md +100 -0
  27. data/docs/general/fields.md +31 -0
  28. data/docs/general/getting_started.md +133 -0
  29. data/docs/general/instrumentation.md +40 -0
  30. data/docs/general/key_transforms.md +40 -0
  31. data/docs/general/logging.md +21 -0
  32. data/docs/general/rendering.md +293 -0
  33. data/docs/general/serializers.md +495 -0
  34. data/docs/how-open-source-maintained.jpg +0 -0
  35. data/docs/howto/add_pagination_links.md +138 -0
  36. data/docs/howto/add_relationship_links.md +140 -0
  37. data/docs/howto/add_root_key.md +62 -0
  38. data/docs/howto/grape_integration.md +42 -0
  39. data/docs/howto/outside_controller_use.md +66 -0
  40. data/docs/howto/passing_arbitrary_options.md +27 -0
  41. data/docs/howto/serialize_poro.md +73 -0
  42. data/docs/howto/test.md +154 -0
  43. data/docs/howto/upgrade_from_0_8_to_0_10.md +265 -0
  44. data/docs/integrations/ember-and-json-api.md +147 -0
  45. data/docs/integrations/grape.md +19 -0
  46. data/docs/jsonapi/errors.md +56 -0
  47. data/docs/jsonapi/schema.md +151 -0
  48. data/docs/jsonapi/schema/schema.json +366 -0
  49. data/docs/rfcs/0000-namespace.md +106 -0
  50. data/docs/rfcs/template.md +15 -0
  51. data/lib/action_controller/serialization.rb +76 -0
  52. data/lib/active_model/serializable_resource.rb +13 -0
  53. data/lib/active_model/serializer.rb +418 -0
  54. data/lib/active_model/serializer/adapter.rb +26 -0
  55. data/lib/active_model/serializer/adapter/attributes.rb +17 -0
  56. data/lib/active_model/serializer/adapter/base.rb +20 -0
  57. data/lib/active_model/serializer/adapter/json.rb +17 -0
  58. data/lib/active_model/serializer/adapter/json_api.rb +17 -0
  59. data/lib/active_model/serializer/adapter/null.rb +17 -0
  60. data/lib/active_model/serializer/array_serializer.rb +14 -0
  61. data/lib/active_model/serializer/association.rb +91 -0
  62. data/lib/active_model/serializer/attribute.rb +27 -0
  63. data/lib/active_model/serializer/belongs_to_reflection.rb +13 -0
  64. data/lib/active_model/serializer/collection_serializer.rb +90 -0
  65. data/lib/active_model/serializer/concerns/caching.rb +304 -0
  66. data/lib/active_model/serializer/error_serializer.rb +16 -0
  67. data/lib/active_model/serializer/errors_serializer.rb +34 -0
  68. data/lib/active_model/serializer/field.rb +92 -0
  69. data/lib/active_model/serializer/fieldset.rb +33 -0
  70. data/lib/active_model/serializer/has_many_reflection.rb +12 -0
  71. data/lib/active_model/serializer/has_one_reflection.rb +9 -0
  72. data/lib/active_model/serializer/lazy_association.rb +99 -0
  73. data/lib/active_model/serializer/link.rb +23 -0
  74. data/lib/active_model/serializer/lint.rb +152 -0
  75. data/lib/active_model/serializer/null.rb +19 -0
  76. data/lib/active_model/serializer/reflection.rb +212 -0
  77. data/lib/active_model/serializer/version.rb +7 -0
  78. data/lib/active_model_serializers.rb +63 -0
  79. data/lib/active_model_serializers/adapter.rb +100 -0
  80. data/lib/active_model_serializers/adapter/attributes.rb +15 -0
  81. data/lib/active_model_serializers/adapter/base.rb +85 -0
  82. data/lib/active_model_serializers/adapter/json.rb +23 -0
  83. data/lib/active_model_serializers/adapter/json_api.rb +535 -0
  84. data/lib/active_model_serializers/adapter/json_api/deserialization.rb +215 -0
  85. data/lib/active_model_serializers/adapter/json_api/error.rb +98 -0
  86. data/lib/active_model_serializers/adapter/json_api/jsonapi.rb +51 -0
  87. data/lib/active_model_serializers/adapter/json_api/link.rb +85 -0
  88. data/lib/active_model_serializers/adapter/json_api/meta.rb +39 -0
  89. data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +90 -0
  90. data/lib/active_model_serializers/adapter/json_api/relationship.rb +106 -0
  91. data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +68 -0
  92. data/lib/active_model_serializers/adapter/null.rb +11 -0
  93. data/lib/active_model_serializers/callbacks.rb +57 -0
  94. data/lib/active_model_serializers/deprecate.rb +56 -0
  95. data/lib/active_model_serializers/deserialization.rb +17 -0
  96. data/lib/active_model_serializers/json_pointer.rb +16 -0
  97. data/lib/active_model_serializers/logging.rb +124 -0
  98. data/lib/active_model_serializers/lookup_chain.rb +82 -0
  99. data/lib/active_model_serializers/model.rb +132 -0
  100. data/lib/active_model_serializers/railtie.rb +52 -0
  101. data/lib/active_model_serializers/register_jsonapi_renderer.rb +80 -0
  102. data/lib/active_model_serializers/serializable_resource.rb +84 -0
  103. data/lib/active_model_serializers/serialization_context.rb +41 -0
  104. data/lib/active_model_serializers/test.rb +9 -0
  105. data/lib/active_model_serializers/test/schema.rb +140 -0
  106. data/lib/active_model_serializers/test/serializer.rb +127 -0
  107. data/lib/generators/rails/USAGE +6 -0
  108. data/lib/generators/rails/resource_override.rb +12 -0
  109. data/lib/generators/rails/serializer_generator.rb +38 -0
  110. data/lib/generators/rails/templates/serializer.rb.erb +8 -0
  111. data/lib/grape/active_model_serializers.rb +18 -0
  112. data/lib/grape/formatters/active_model_serializers.rb +34 -0
  113. data/lib/grape/helpers/active_model_serializers.rb +19 -0
  114. data/lib/tasks/rubocop.rake +55 -0
  115. data/test/action_controller/adapter_selector_test.rb +64 -0
  116. data/test/action_controller/explicit_serializer_test.rb +137 -0
  117. data/test/action_controller/json/include_test.rb +248 -0
  118. data/test/action_controller/json_api/deserialization_test.rb +114 -0
  119. data/test/action_controller/json_api/errors_test.rb +42 -0
  120. data/test/action_controller/json_api/fields_test.rb +68 -0
  121. data/test/action_controller/json_api/linked_test.rb +204 -0
  122. data/test/action_controller/json_api/pagination_test.rb +126 -0
  123. data/test/action_controller/json_api/transform_test.rb +191 -0
  124. data/test/action_controller/lookup_proc_test.rb +51 -0
  125. data/test/action_controller/namespace_lookup_test.rb +239 -0
  126. data/test/action_controller/serialization_scope_name_test.rb +237 -0
  127. data/test/action_controller/serialization_test.rb +480 -0
  128. data/test/active_model_serializers/adapter_for_test.rb +210 -0
  129. data/test/active_model_serializers/json_pointer_test.rb +24 -0
  130. data/test/active_model_serializers/logging_test.rb +79 -0
  131. data/test/active_model_serializers/model_test.rb +144 -0
  132. data/test/active_model_serializers/railtie_test_isolated.rb +70 -0
  133. data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +163 -0
  134. data/test/active_model_serializers/serialization_context_test_isolated.rb +73 -0
  135. data/test/active_model_serializers/test/schema_test.rb +133 -0
  136. data/test/active_model_serializers/test/serializer_test.rb +64 -0
  137. data/test/active_record_test.rb +11 -0
  138. data/test/adapter/attributes_test.rb +42 -0
  139. data/test/adapter/deprecation_test.rb +102 -0
  140. data/test/adapter/json/belongs_to_test.rb +47 -0
  141. data/test/adapter/json/collection_test.rb +106 -0
  142. data/test/adapter/json/has_many_test.rb +55 -0
  143. data/test/adapter/json/transform_test.rb +95 -0
  144. data/test/adapter/json_api/belongs_to_test.rb +157 -0
  145. data/test/adapter/json_api/collection_test.rb +98 -0
  146. data/test/adapter/json_api/errors_test.rb +78 -0
  147. data/test/adapter/json_api/fields_test.rb +98 -0
  148. data/test/adapter/json_api/has_many_explicit_serializer_test.rb +98 -0
  149. data/test/adapter/json_api/has_many_test.rb +175 -0
  150. data/test/adapter/json_api/has_one_test.rb +82 -0
  151. data/test/adapter/json_api/include_data_if_sideloaded_test.rb +215 -0
  152. data/test/adapter/json_api/json_api_test.rb +35 -0
  153. data/test/adapter/json_api/linked_test.rb +415 -0
  154. data/test/adapter/json_api/links_test.rb +112 -0
  155. data/test/adapter/json_api/pagination_links_test.rb +208 -0
  156. data/test/adapter/json_api/parse_test.rb +139 -0
  157. data/test/adapter/json_api/relationship_test.rb +399 -0
  158. data/test/adapter/json_api/resource_meta_test.rb +102 -0
  159. data/test/adapter/json_api/toplevel_jsonapi_test.rb +84 -0
  160. data/test/adapter/json_api/transform_test.rb +514 -0
  161. data/test/adapter/json_api/type_test.rb +195 -0
  162. data/test/adapter/json_test.rb +48 -0
  163. data/test/adapter/null_test.rb +24 -0
  164. data/test/adapter/polymorphic_test.rb +220 -0
  165. data/test/adapter_test.rb +69 -0
  166. data/test/array_serializer_test.rb +24 -0
  167. data/test/benchmark/app.rb +67 -0
  168. data/test/benchmark/benchmarking_support.rb +69 -0
  169. data/test/benchmark/bm_active_record.rb +83 -0
  170. data/test/benchmark/bm_adapter.rb +40 -0
  171. data/test/benchmark/bm_caching.rb +121 -0
  172. data/test/benchmark/bm_lookup_chain.rb +85 -0
  173. data/test/benchmark/bm_transform.rb +47 -0
  174. data/test/benchmark/config.ru +3 -0
  175. data/test/benchmark/controllers.rb +85 -0
  176. data/test/benchmark/fixtures.rb +221 -0
  177. data/test/cache_test.rb +717 -0
  178. data/test/collection_serializer_test.rb +129 -0
  179. data/test/fixtures/active_record.rb +115 -0
  180. data/test/fixtures/poro.rb +227 -0
  181. data/test/generators/scaffold_controller_generator_test.rb +26 -0
  182. data/test/generators/serializer_generator_test.rb +77 -0
  183. data/test/grape_test.rb +198 -0
  184. data/test/lint_test.rb +51 -0
  185. data/test/logger_test.rb +22 -0
  186. data/test/poro_test.rb +11 -0
  187. data/test/serializable_resource_test.rb +81 -0
  188. data/test/serializers/association_macros_test.rb +39 -0
  189. data/test/serializers/associations_test.rb +520 -0
  190. data/test/serializers/attribute_test.rb +155 -0
  191. data/test/serializers/attributes_test.rb +54 -0
  192. data/test/serializers/caching_configuration_test_isolated.rb +172 -0
  193. data/test/serializers/configuration_test.rb +34 -0
  194. data/test/serializers/fieldset_test.rb +16 -0
  195. data/test/serializers/meta_test.rb +204 -0
  196. data/test/serializers/options_test.rb +34 -0
  197. data/test/serializers/read_attribute_for_serialization_test.rb +81 -0
  198. data/test/serializers/reflection_test.rb +481 -0
  199. data/test/serializers/root_test.rb +23 -0
  200. data/test/serializers/serialization_test.rb +57 -0
  201. data/test/serializers/serializer_for_test.rb +138 -0
  202. data/test/serializers/serializer_for_with_namespace_test.rb +90 -0
  203. data/test/support/custom_schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
  204. data/test/support/isolated_unit.rb +86 -0
  205. data/test/support/rails5_shims.rb +55 -0
  206. data/test/support/rails_app.rb +40 -0
  207. data/test/support/schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
  208. data/test/support/schemas/active_model_serializers/test/schema_test/my/show.json +6 -0
  209. data/test/support/schemas/custom/show.json +7 -0
  210. data/test/support/schemas/hyper_schema.json +93 -0
  211. data/test/support/schemas/render_using_json_api.json +43 -0
  212. data/test/support/schemas/simple_json_pointers.json +10 -0
  213. data/test/support/serialization_testing.rb +81 -0
  214. data/test/test_helper.rb +72 -0
  215. metadata +622 -0
@@ -0,0 +1,147 @@
1
+ [Back to Guides](../README.md)
2
+
3
+ # Integrating with Ember and JSON API
4
+
5
+ - [Preparation](./ember-and-json-api.md#preparation)
6
+ - [Server-Side Changes](./ember-and-json-api.md#server-side-changes)
7
+ - [Adapter Changes](./ember-and-json-api.md#adapter-changes)
8
+ - [Serializer Changes](./ember-and-json-api.md#serializer-changes)
9
+ - [Including Nested Resources](./ember-and-json-api.md#including-nested-resources)
10
+
11
+ ## Preparation
12
+
13
+ Note: This guide assumes that `ember-cli` is used for your ember app.
14
+
15
+ The JSON API specification calls for hyphens for multi-word separators. ActiveModelSerializers uses underscores.
16
+ To solve this, in Ember, both the adapter and the serializer will need some modifications:
17
+
18
+ ### Server-Side Changes
19
+
20
+ First, set the adapter type in an initializer file:
21
+
22
+ ```ruby
23
+ # config/initializers/active_model_serializers.rb
24
+ ActiveModelSerializers.config.adapter = :json_api
25
+ ```
26
+
27
+ or:
28
+
29
+ ```ruby
30
+ # config/initializers/active_model_serializers.rb
31
+ ActiveModelSerializers.config.adapter = ActiveModelSerializers::Adapter::JsonApi
32
+ ```
33
+
34
+ You will also want to set the `key_transform` to `:unaltered` since you will adjust the attributes in your Ember serializer to use underscores instead of dashes later. You could also use `:underscore`, but `:unaltered` is better for performance.
35
+
36
+ ```ruby
37
+ # config/initializers/active_model_serializers.rb
38
+ ActiveModelSerializers.config.key_transform = :unaltered
39
+ ```
40
+
41
+ In order to properly handle JSON API responses, we need to register a JSON API renderer, like so:
42
+
43
+ ```ruby
44
+ # config/initializers/active_model_serializers.rb
45
+ ActiveSupport.on_load(:action_controller) do
46
+ require 'active_model_serializers/register_jsonapi_renderer'
47
+ end
48
+ ```
49
+ Rails also requires your controller to tell it that you accept and generate JSONAPI data. To do that, you use `respond_to` in your controller handlers to tell rails you are consuming and returning jsonapi format data. Without this, Rails will refuse to parse the request body into params. You can add `ActionController::MimeResponds` to your application controller to enable this:
50
+
51
+ ```ruby
52
+ class ApplicationController < ActionController::API
53
+ include ActionController::MimeResponds
54
+ end
55
+ ```
56
+ Then, in your controller you can tell rails you're accepting and rendering the jsonapi format:
57
+ ```ruby
58
+ # POST /post
59
+ def create
60
+ @post = Post.new(post_params)
61
+ respond_to do |format|
62
+ if @post.save
63
+ format.jsonapi { render jsonapi: @post, status: :created, location: @post }
64
+ else
65
+ format.jsonapi { render jsonapi: @post.errors, status: :unprocessable_entity }
66
+ end
67
+ end
68
+ end
69
+
70
+ # Only allow a trusted parameter "white list" through.
71
+ def post_params
72
+ ActiveModelSerializers::Deserialization.jsonapi_parse!(params, only: [:title, :body] )
73
+ end
74
+ end
75
+ ```
76
+
77
+ #### Note:
78
+ In Rails 5, the "unsafe" method ( `jsonapi_parse!` vs the safe `jsonapi_parse`) throws an `InvalidDocument` exception when the payload does not meet basic criteria for JSON API deserialization.
79
+
80
+
81
+ ### Adapter Changes
82
+
83
+ ```javascript
84
+ // app/adapters/application.js
85
+ import Ember from 'ember';
86
+ import DS from 'ember-data';
87
+ import ENV from "../config/environment";
88
+ const { underscore, pluralize } = Ember.String;
89
+
90
+ export default DS.JSONAPIAdapter.extend({
91
+ namespace: 'api',
92
+ // if your rails app is on a different port from your ember app
93
+ // this can be helpful for development.
94
+ // in production, the host for both rails and ember should be the same.
95
+ host: ENV.host,
96
+
97
+ // allows the multiword paths in urls to be underscored
98
+ pathForType: function(type) {
99
+ let underscored = underscore(type);
100
+ return pluralize(underscored);
101
+ },
102
+
103
+ });
104
+ ```
105
+
106
+ ### Serializer Changes
107
+
108
+ ```javascript
109
+ // app/serializers/application.js
110
+ import Ember from 'ember';
111
+ import DS from 'ember-data';
112
+ var underscore = Ember.String.underscore;
113
+
114
+ export default DS.JSONAPISerializer.extend({
115
+ keyForAttribute: function(attr) {
116
+ return underscore(attr);
117
+ },
118
+
119
+ keyForRelationship: function(rawKey) {
120
+ return underscore(rawKey);
121
+ }
122
+ });
123
+
124
+ ```
125
+
126
+
127
+ ## Including Nested Resources
128
+
129
+ Ember Data can request related records by using `include`. Below are some examples of how to make Ember Data request the inclusion of related records. For more on `include` usage, see: [The JSON API include examples](./../general/adapters.md#JSON-API)
130
+
131
+ ```javascript
132
+ store.findRecord('post', postId, { include: 'comments' } );
133
+ ```
134
+ which will generate the path /posts/{postId}?include='comments'
135
+
136
+ So then in your controller, you'll want to be sure to have something like:
137
+ ```ruby
138
+ render jsonapi: @post, include: params[:include]
139
+ ```
140
+
141
+ If you want to use `include` on a collection, you'd write something like this:
142
+
143
+ ```javascript
144
+ store.query('post', { include: 'comments' });
145
+ ```
146
+
147
+ which will generate the path `/posts?include='comments'`
@@ -0,0 +1,19 @@
1
+ # Integration with Grape
2
+
3
+ [Grape](https://github.com/ruby-grape/grape) is an opinionated micro-framework for creating REST-like APIs in ruby.
4
+
5
+ ActiveModelSerializers currently supports Grape >= 0.13, < 1.0
6
+
7
+ To add [Grape](https://github.com/ruby-grape/grape) support, enable the formatter and helper functions by including `Grape::ActiveModelSerializers` in your base endpoint. For example:
8
+
9
+ ```ruby
10
+ module Example
11
+ class Dummy < Grape::API
12
+ require 'grape/active_model_serializers'
13
+ include Grape::ActiveModelSerializers
14
+ mount Example::V1::Base
15
+ end
16
+ end
17
+ ```
18
+
19
+ Aside from this, [configuration](../general/configuration_options.md) of ActiveModelSerializers is exactly the same.
@@ -0,0 +1,56 @@
1
+ [Back to Guides](../README.md)
2
+
3
+ # [JSON API Errors](http://jsonapi.org/format/#errors)
4
+
5
+ Rendering error documents requires specifying the error serializer(s):
6
+
7
+ - Serializer:
8
+ - For a single resource: `serializer: ActiveModel::Serializer::ErrorSerializer`.
9
+ - For a collection: `serializer: ActiveModel::Serializer::ErrorsSerializer`, `each_serializer: ActiveModel::Serializer::ErrorSerializer`.
10
+
11
+ The resource **MUST** have a non-empty associated `#errors` object.
12
+ The `errors` object must have a `#messages` method that returns a hash of error name to array of
13
+ descriptions.
14
+
15
+ ## Use in controllers
16
+
17
+ ```ruby
18
+ resource = Profile.new(name: 'Name 1',
19
+ description: 'Description 1',
20
+ comments: 'Comments 1')
21
+ resource.errors.add(:name, 'cannot be nil')
22
+ resource.errors.add(:name, 'must be longer')
23
+ resource.errors.add(:id, 'must be a uuid')
24
+
25
+ render json: resource, status: 422, adapter: :json_api, serializer: ActiveModel::Serializer::ErrorSerializer
26
+ # #=>
27
+ # { :errors =>
28
+ # [
29
+ # { :source => { :pointer => '/data/attributes/name' }, :detail => 'cannot be nil' },
30
+ # { :source => { :pointer => '/data/attributes/name' }, :detail => 'must be longer' },
31
+ # { :source => { :pointer => '/data/attributes/id' }, :detail => 'must be a uuid' }
32
+ # ]
33
+ # }.to_json
34
+ ```
35
+
36
+ ## Direct error document generation
37
+
38
+ ```ruby
39
+ options = nil
40
+ resource = ModelWithErrors.new
41
+ resource.errors.add(:name, 'must be awesome')
42
+
43
+ serializable_resource = ActiveModelSerializers::SerializableResource.new(
44
+ resource, {
45
+ serializer: ActiveModel::Serializer::ErrorSerializer,
46
+ adapter: :json_api
47
+ })
48
+ serializable_resource.as_json(options)
49
+ # #=>
50
+ # {
51
+ # :errors =>
52
+ # [
53
+ # { :source => { :pointer => '/data/attributes/name' }, :detail => 'must be awesome' }
54
+ # ]
55
+ # }
56
+ ```
@@ -0,0 +1,151 @@
1
+ [Back to Guides](../README.md)
2
+
3
+ [![JSON API 1.0](https://img.shields.io/badge/JSON%20API-1.0-lightgrey.svg)](http://jsonapi.org/)
4
+
5
+ ## JSON API Requests
6
+
7
+ - [Query Parameters Spec](http://jsonapi.org/format/#query-parameters)
8
+
9
+ Headers:
10
+
11
+ - Request: `Accept: application/vnd.api+json`
12
+ - Response: `Content-Type: application/vnd.api+json`
13
+
14
+ ### [Fetching Data](http://jsonapi.org/format/#fetching)
15
+
16
+ A server MUST support fetching resource data for every URL provided as:
17
+
18
+ - a `self` link as part of the top-level links object
19
+ - a `self` link as part of a resource-level links object
20
+ - a `related` link as part of a relationship-level links object
21
+
22
+ Example supported requests
23
+
24
+ - Individual resource or collection
25
+ - GET /articles
26
+ - GET /articles/1
27
+ - GET /articles/1/author
28
+ - Relationships
29
+ - GET /articles/1/relationships/comments
30
+ - GET /articles/1/relationships/author
31
+ - Optional: [Inclusion of related resources](http://jsonapi.org/format/#fetching-includes) `JSONAPI::IncludeDirective`
32
+ - GET /articles/1?`include`=comments
33
+ - GET /articles/1?`include`=comments.author
34
+ - GET /articles/1?`include`=author,comments.author
35
+ - GET /articles/1/relationships/comments?`include`=comments.author
36
+ - Optional: [Sparse Fieldsets](http://jsonapi.org/format/#fetching-sparse-fieldsets) `ActiveModel::Serializer::Fieldset`
37
+ - GET /articles?`include`=author&`fields`[articles]=title,body&`fields`[people]=name
38
+ - Optional: [Sorting](http://jsonapi.org/format/#fetching-sorting)
39
+ - GET /people?`sort`=age
40
+ - GET /people?`sort`=age,author.name
41
+ - GET /articles?`sort`=-created,title
42
+ - Optional: [Pagination](http://jsonapi.org/format/#fetching-pagination)
43
+ - GET /articles?`page`[number]=3&`page`[size]=1
44
+ - Optional: [Filtering](http://jsonapi.org/format/#fetching-filtering)
45
+ - GET /comments?`filter`[post]=1
46
+ - GET /comments?`filter`[post]=1,2
47
+ - GET /comments?`filter`[post]=1,2
48
+
49
+ ### [CRUD Actions](http://jsonapi.org/format/#crud)
50
+
51
+ ### [Asynchronous Processing](http://jsonapi.org/recommendations/#asynchronous-processing)
52
+
53
+ ### [Bulk Operations Extension](http://jsonapi.org/extensions/bulk/)
54
+
55
+ ## JSON API Document Schema
56
+
57
+ | JSON API object | JSON API properties | Required | ActiveModelSerializers representation |
58
+ |-----------------------|----------------------------------------------------------------------------------------------------|----------|---------------------------------------|
59
+ | schema | oneOf (success, failure, info) | |
60
+ | success | data, included, meta, links, jsonapi | | AM::SerializableResource
61
+ | success.meta | meta | | AMS::Adapter::Base#meta
62
+ | success.included | UniqueArray(resource) | | AMS::Adapter::JsonApi#serializable_hash_for_collection
63
+ | success.data | data | |
64
+ | success.links | allOf (links, pagination) | | AMS::Adapter::JsonApi#links_for
65
+ | success.jsonapi | jsonapi | |
66
+ | failure | errors, meta, jsonapi | errors | AMS::Adapter::JsonApi#failure_document, #1004
67
+ | failure.errors | UniqueArray(error) | | AM::S::ErrorSerializer, #1004
68
+ | meta | Object | |
69
+ | data | oneOf (resource, UniqueArray(resource)) | | AMS::Adapter::JsonApi#serializable_hash_for_collection,#serializable_hash_for_single_resource
70
+ | resource | String(type), String(id),<br>attributes, relationships,<br>links, meta | type, id | AM::S::Adapter::JsonApi#primary_data_for
71
+ | links | Uri(self), Link(related) | | #1028, #1246, #1282
72
+ | link | oneOf (linkString, linkObject) | |
73
+ | link.linkString | Uri | |
74
+ | link.linkObject | Uri(href), meta | href |
75
+ | attributes | patternProperties(<br>`"^(?!relationships$|links$)\\w[-\\w_]*$"`),<br>any valid JSON | | AM::Serializer#attributes, AMS::Adapter::JsonApi#resource_object_for
76
+ | relationships | patternProperties(<br>`"^\\w[-\\w_]*$"`);<br>links, relationships.data, meta | | AMS::Adapter::JsonApi#relationships_for
77
+ | relationships.data | oneOf (relationshipToOne, relationshipToMany) | | AMS::Adapter::JsonApi#resource_identifier_for
78
+ | relationshipToOne | anyOf(empty, linkage) | |
79
+ | relationshipToMany | UniqueArray(linkage) | |
80
+ | empty | null | |
81
+ | linkage | String(type), String(id), meta | type, id | AMS::Adapter::JsonApi#primary_data_for
82
+ | pagination | pageObject(first), pageObject(last),<br>pageObject(prev), pageObject(next) | | AMS::Adapter::JsonApi::PaginationLinks#serializable_hash
83
+ | pagination.pageObject | oneOf(Uri, null) | |
84
+ | jsonapi | String(version), meta | | AMS::Adapter::JsonApi::Jsonapi#as_json
85
+ | error | String(id), links, String(status),<br>String(code), String(title),<br>String(detail), error.source, meta | | AM::S::ErrorSerializer, AMS::Adapter::JsonApi::Error.resource_errors
86
+ | error.source | String(pointer), String(parameter) | | AMS::Adapter::JsonApi::Error.error_source
87
+ | pointer | [JSON Pointer RFC6901](https://tools.ietf.org/html/rfc6901) | | AMS::JsonPointer
88
+
89
+
90
+ The [http://jsonapi.org/schema](schema/schema.json) makes a nice roadmap.
91
+
92
+ ### Success Document
93
+ - [ ] success
94
+ - [ ] data: `"$ref": "#/definitions/data"`
95
+ - [ ] included: array of unique items of type `"$ref": "#/definitions/resource"`
96
+ - [ ] meta: `"$ref": "#/definitions/meta"`
97
+ - [ ] links:
98
+ - [ ] link: `"$ref": "#/definitions/links"`
99
+ - [ ] pagination: ` "$ref": "#/definitions/pagination"`
100
+ - [ ] jsonapi: ` "$ref": "#/definitions/jsonapi"`
101
+
102
+ ### Failure Document
103
+
104
+ - [ ] failure
105
+ - [x] errors: array of unique items of type ` "$ref": "#/definitions/error"`
106
+ - [ ] meta: `"$ref": "#/definitions/meta"`
107
+ - [ ] jsonapi: `"$ref": "#/definitions/jsonapi"`
108
+
109
+ ### Info Document
110
+
111
+ - [ ] info
112
+ - [ ] meta: `"$ref": "#/definitions/meta"`
113
+ - [ ] links: `"$ref": "#/definitions/links"`
114
+ - [ ] jsonapi: ` "$ref": "#/definitions/jsonapi"`
115
+
116
+ ### Definitions
117
+
118
+ - [ ] definitions:
119
+ - [ ] meta
120
+ - [ ] data: oneOf (resource, array of unique resources)
121
+ - [ ] resource
122
+ - [ ] attributes
123
+ - [ ] relationships
124
+ - [ ] relationshipToOne
125
+ - [ ] empty
126
+ - [ ] linkage
127
+ - [ ] meta
128
+ - [ ] relationshipToMany
129
+ - [ ] linkage
130
+ - [ ] meta
131
+ - [ ] links
132
+ - [ ] meta
133
+ - [ ] links
134
+ - [ ] link
135
+ - [ ] uri
136
+ - [ ] href, meta
137
+ - [ ] pagination
138
+ - [ ] jsonapi
139
+ - [ ] meta
140
+ - [ ] error
141
+ - [ ] id: a unique identifier for this particular occurrence of the problem.
142
+ - [ ] links: a links object containing the following members:
143
+ - [ ] about: a link that leads to further details about this particular occurrence of the problem.
144
+ - [ ] status: the HTTP status code applicable to this problem, expressed as a string value.
145
+ - [ ] code: an application-specific error code, expressed as a string value.
146
+ - [ ] title: a short, human-readable summary of the problem that SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization.
147
+ - [x] detail: a human-readable explanation specific to this occurrence of the problem.
148
+ - [x] source: an object containing references to the source of the error, optionally including any of the following members:
149
+ - [x] pointer: a JSON Pointer [RFC6901](https://tools.ietf.org/html/rfc6901) to the associated entity in the request document [e.g. "/data" for a primary data object, or "/data/attributes/title" for a specific attribute].
150
+ - [x] parameter: a string indicating which query parameter caused the error.
151
+ - [ ] meta: a meta object containing non-standard meta-information about the error.
@@ -0,0 +1,366 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-04/schema#",
3
+ "title": "JSON API Schema",
4
+ "description": "This is a schema for responses in the JSON API format. For more, see http://jsonapi.org",
5
+ "oneOf": [
6
+ {
7
+ "$ref": "#/definitions/success"
8
+ },
9
+ {
10
+ "$ref": "#/definitions/failure"
11
+ },
12
+ {
13
+ "$ref": "#/definitions/info"
14
+ }
15
+ ],
16
+
17
+ "definitions": {
18
+ "success": {
19
+ "type": "object",
20
+ "required": [
21
+ "data"
22
+ ],
23
+ "properties": {
24
+ "data": {
25
+ "$ref": "#/definitions/data"
26
+ },
27
+ "included": {
28
+ "description": "To reduce the number of HTTP requests, servers **MAY** allow responses that include related resources along with the requested primary resources. Such responses are called \"compound documents\".",
29
+ "type": "array",
30
+ "items": {
31
+ "$ref": "#/definitions/resource"
32
+ },
33
+ "uniqueItems": true
34
+ },
35
+ "meta": {
36
+ "$ref": "#/definitions/meta"
37
+ },
38
+ "links": {
39
+ "description": "Link members related to the primary data.",
40
+ "allOf": [
41
+ {
42
+ "$ref": "#/definitions/links"
43
+ },
44
+ {
45
+ "$ref": "#/definitions/pagination"
46
+ }
47
+ ]
48
+ },
49
+ "jsonapi": {
50
+ "$ref": "#/definitions/jsonapi"
51
+ }
52
+ },
53
+ "additionalProperties": false
54
+ },
55
+ "failure": {
56
+ "type": "object",
57
+ "required": [
58
+ "errors"
59
+ ],
60
+ "properties": {
61
+ "errors": {
62
+ "type": "array",
63
+ "items": {
64
+ "$ref": "#/definitions/error"
65
+ },
66
+ "uniqueItems": true
67
+ },
68
+ "meta": {
69
+ "$ref": "#/definitions/meta"
70
+ },
71
+ "jsonapi": {
72
+ "$ref": "#/definitions/jsonapi"
73
+ }
74
+ },
75
+ "additionalProperties": false
76
+ },
77
+ "info": {
78
+ "type": "object",
79
+ "required": [
80
+ "meta"
81
+ ],
82
+ "properties": {
83
+ "meta": {
84
+ "$ref": "#/definitions/meta"
85
+ },
86
+ "links": {
87
+ "$ref": "#/definitions/links"
88
+ },
89
+ "jsonapi": {
90
+ "$ref": "#/definitions/jsonapi"
91
+ }
92
+ },
93
+ "additionalProperties": false
94
+ },
95
+
96
+ "meta": {
97
+ "description": "Non-standard meta-information that can not be represented as an attribute or relationship.",
98
+ "type": "object",
99
+ "additionalProperties": true
100
+ },
101
+ "data": {
102
+ "description": "The document's \"primary data\" is a representation of the resource or collection of resources targeted by a request.",
103
+ "oneOf": [
104
+ {
105
+ "$ref": "#/definitions/resource"
106
+ },
107
+ {
108
+ "description": "An array of resource objects, an array of resource identifier objects, or an empty array ([]), for requests that target resource collections.",
109
+ "type": "array",
110
+ "items": {
111
+ "$ref": "#/definitions/resource"
112
+ },
113
+ "uniqueItems": true
114
+ }
115
+ ]
116
+ },
117
+ "resource": {
118
+ "description": "\"Resource objects\" appear in a JSON API document to represent resources.",
119
+ "type": "object",
120
+ "required": [
121
+ "type",
122
+ "id"
123
+ ],
124
+ "properties": {
125
+ "type": {
126
+ "type": "string"
127
+ },
128
+ "id": {
129
+ "type": "string"
130
+ },
131
+ "attributes": {
132
+ "$ref": "#/definitions/attributes"
133
+ },
134
+ "relationships": {
135
+ "$ref": "#/definitions/relationships"
136
+ },
137
+ "links": {
138
+ "$ref": "#/definitions/links"
139
+ },
140
+ "meta": {
141
+ "$ref": "#/definitions/meta"
142
+ }
143
+ },
144
+ "additionalProperties": false
145
+ },
146
+
147
+ "links": {
148
+ "description": "A resource object **MAY** contain references to other resource objects (\"relationships\"). Relationships may be to-one or to-many. Relationships can be specified by including a member in a resource's links object.",
149
+ "type": "object",
150
+ "properties": {
151
+ "self": {
152
+ "description": "A `self` member, whose value is a URL for the relationship itself (a \"relationship URL\"). This URL allows the client to directly manipulate the relationship. For example, it would allow a client to remove an `author` from an `article` without deleting the people resource itself.",
153
+ "type": "string",
154
+ "format": "uri"
155
+ },
156
+ "related": {
157
+ "$ref": "#/definitions/link"
158
+ }
159
+ },
160
+ "additionalProperties": true
161
+ },
162
+ "link": {
163
+ "description": "A link **MUST** be represented as either: a string containing the link's URL or a link object.",
164
+ "oneOf": [
165
+ {
166
+ "description": "A string containing the link's URL.",
167
+ "type": "string",
168
+ "format": "uri"
169
+ },
170
+ {
171
+ "type": "object",
172
+ "required": [
173
+ "href"
174
+ ],
175
+ "properties": {
176
+ "href": {
177
+ "description": "A string containing the link's URL.",
178
+ "type": "string",
179
+ "format": "uri"
180
+ },
181
+ "meta": {
182
+ "$ref": "#/definitions/meta"
183
+ }
184
+ }
185
+ }
186
+ ]
187
+ },
188
+
189
+ "attributes": {
190
+ "description": "Members of the attributes object (\"attributes\") represent information about the resource object in which it's defined.",
191
+ "type": "object",
192
+ "patternProperties": {
193
+ "^(?!relationships$|links$)\\w[-\\w_]*$": {
194
+ "description": "Attributes may contain any valid JSON value."
195
+ }
196
+ },
197
+ "additionalProperties": false
198
+ },
199
+
200
+ "relationships": {
201
+ "description": "Members of the relationships object (\"relationships\") represent references from the resource object in which it's defined to other resource objects.",
202
+ "type": "object",
203
+ "patternProperties": {
204
+ "^\\w[-\\w_]*$": {
205
+ "properties": {
206
+ "links": {
207
+ "$ref": "#/definitions/links"
208
+ },
209
+ "data": {
210
+ "description": "Member, whose value represents \"resource linkage\".",
211
+ "oneOf": [
212
+ {
213
+ "$ref": "#/definitions/relationshipToOne"
214
+ },
215
+ {
216
+ "$ref": "#/definitions/relationshipToMany"
217
+ }
218
+ ]
219
+ },
220
+ "meta": {
221
+ "$ref": "#/definitions/meta"
222
+ }
223
+ },
224
+ "additionalProperties": false
225
+ }
226
+ },
227
+ "additionalProperties": false
228
+ },
229
+ "relationshipToOne": {
230
+ "description": "References to other resource objects in a to-one (\"relationship\"). Relationships can be specified by including a member in a resource's links object.",
231
+ "anyOf": [
232
+ {
233
+ "$ref": "#/definitions/empty"
234
+ },
235
+ {
236
+ "$ref": "#/definitions/linkage"
237
+ }
238
+ ]
239
+ },
240
+ "relationshipToMany": {
241
+ "description": "An array of objects each containing \"type\" and \"id\" members for to-many relationships.",
242
+ "type": "array",
243
+ "items": {
244
+ "$ref": "#/definitions/linkage"
245
+ },
246
+ "uniqueItems": true
247
+ },
248
+ "empty": {
249
+ "description": "Describes an empty to-one relationship.",
250
+ "type": "null"
251
+ },
252
+ "linkage": {
253
+ "description": "The \"type\" and \"id\" to non-empty members.",
254
+ "type": "object",
255
+ "required": [
256
+ "type",
257
+ "id"
258
+ ],
259
+ "properties": {
260
+ "type": {
261
+ "type": "string"
262
+ },
263
+ "id": {
264
+ "type": "string"
265
+ },
266
+ "meta": {
267
+ "$ref": "#/definitions/meta"
268
+ }
269
+ },
270
+ "additionalProperties": false
271
+ },
272
+ "pagination": {
273
+ "type": "object",
274
+ "properties": {
275
+ "first": {
276
+ "description": "The first page of data",
277
+ "oneOf": [
278
+ { "type": "string", "format": "uri" },
279
+ { "type": "null" }
280
+ ]
281
+ },
282
+ "last": {
283
+ "description": "The last page of data",
284
+ "oneOf": [
285
+ { "type": "string", "format": "uri" },
286
+ { "type": "null" }
287
+ ]
288
+ },
289
+ "prev": {
290
+ "description": "The previous page of data",
291
+ "oneOf": [
292
+ { "type": "string", "format": "uri" },
293
+ { "type": "null" }
294
+ ]
295
+ },
296
+ "next": {
297
+ "description": "The next page of data",
298
+ "oneOf": [
299
+ { "type": "string", "format": "uri" },
300
+ { "type": "null" }
301
+ ]
302
+ }
303
+ }
304
+ },
305
+
306
+ "jsonapi": {
307
+ "description": "An object describing the server's implementation",
308
+ "type": "object",
309
+ "properties": {
310
+ "version": {
311
+ "type": "string"
312
+ },
313
+ "meta": {
314
+ "$ref": "#/definitions/meta"
315
+ }
316
+ },
317
+ "additionalProperties": false
318
+ },
319
+
320
+ "error": {
321
+ "type": "object",
322
+ "properties": {
323
+ "id": {
324
+ "description": "A unique identifier for this particular occurrence of the problem.",
325
+ "type": "string"
326
+ },
327
+ "links": {
328
+ "$ref": "#/definitions/links"
329
+ },
330
+ "status": {
331
+ "description": "The HTTP status code applicable to this problem, expressed as a string value.",
332
+ "type": "string"
333
+ },
334
+ "code": {
335
+ "description": "An application-specific error code, expressed as a string value.",
336
+ "type": "string"
337
+ },
338
+ "title": {
339
+ "description": "A short, human-readable summary of the problem. It **SHOULD NOT** change from occurrence to occurrence of the problem, except for purposes of localization.",
340
+ "type": "string"
341
+ },
342
+ "detail": {
343
+ "description": "A human-readable explanation specific to this occurrence of the problem.",
344
+ "type": "string"
345
+ },
346
+ "source": {
347
+ "type": "object",
348
+ "properties": {
349
+ "pointer": {
350
+ "description": "A JSON Pointer [RFC6901] to the associated entity in the request document [e.g. \"/data\" for a primary data object, or \"/data/attributes/title\" for a specific attribute].",
351
+ "type": "string"
352
+ },
353
+ "parameter": {
354
+ "description": "A string indicating which query parameter caused the error.",
355
+ "type": "string"
356
+ }
357
+ }
358
+ },
359
+ "meta": {
360
+ "$ref": "#/definitions/meta"
361
+ }
362
+ },
363
+ "additionalProperties": false
364
+ }
365
+ }
366
+ }