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,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ module ActiveModel
6
+ class Serializer
7
+ module Adapter
8
+ class JsonApi
9
+ class ResourceMetaTest < Minitest::Test
10
+ class MetaHashPostSerializer < ActiveModel::Serializer
11
+ attributes :id
12
+ meta stuff: 'value'
13
+ end
14
+
15
+ class MetaBlockPostSerializer < ActiveModel::Serializer
16
+ attributes :id
17
+ meta do
18
+ { comments_count: object.comments.count }
19
+ end
20
+ end
21
+
22
+ class MetaBlockPostBlankMetaSerializer < ActiveModel::Serializer
23
+ attributes :id
24
+ meta do
25
+ {}
26
+ end
27
+ end
28
+
29
+ class MetaBlockPostEmptyStringSerializer < ActiveModel::Serializer
30
+ attributes :id
31
+ meta do
32
+ ''
33
+ end
34
+ end
35
+
36
+ def setup
37
+ @post = Post.new(id: 1337, comments: [], author: nil)
38
+ end
39
+
40
+ def test_meta_hash_object_resource
41
+ hash = ActiveModelSerializers::SerializableResource.new(
42
+ @post,
43
+ serializer: MetaHashPostSerializer,
44
+ adapter: :json_api
45
+ ).serializable_hash
46
+ expected = {
47
+ stuff: 'value'
48
+ }
49
+ assert_equal(expected, hash[:data][:meta])
50
+ end
51
+
52
+ def test_meta_block_object_resource
53
+ hash = ActiveModelSerializers::SerializableResource.new(
54
+ @post,
55
+ serializer: MetaBlockPostSerializer,
56
+ adapter: :json_api
57
+ ).serializable_hash
58
+ expected = {
59
+ :"comments-count" => @post.comments.count
60
+ }
61
+ assert_equal(expected, hash[:data][:meta])
62
+ end
63
+
64
+ def test_meta_object_resource_in_array
65
+ post2 = Post.new(id: 1339, comments: [Comment.new])
66
+ posts = [@post, post2]
67
+ hash = ActiveModelSerializers::SerializableResource.new(
68
+ posts,
69
+ each_serializer: MetaBlockPostSerializer,
70
+ adapter: :json_api
71
+ ).serializable_hash
72
+ expected = {
73
+ data: [
74
+ { id: '1337', type: 'posts', meta: { :"comments-count" => 0 } },
75
+ { id: '1339', type: 'posts', meta: { :"comments-count" => 1 } }
76
+ ]
77
+ }
78
+ assert_equal(expected, hash)
79
+ end
80
+
81
+ def test_meta_object_blank_omitted
82
+ hash = ActiveModelSerializers::SerializableResource.new(
83
+ @post,
84
+ serializer: MetaBlockPostBlankMetaSerializer,
85
+ adapter: :json_api
86
+ ).serializable_hash
87
+ refute hash[:data].key? :meta
88
+ end
89
+
90
+ def test_meta_object_empty_string_omitted
91
+ hash = ActiveModelSerializers::SerializableResource.new(
92
+ @post,
93
+ serializer: MetaBlockPostEmptyStringSerializer,
94
+ adapter: :json_api
95
+ ).serializable_hash
96
+ refute hash[:data].key? :meta
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ module ActiveModelSerializers
6
+ module Adapter
7
+ class JsonApi
8
+ class TopLevelJsonApiTest < ActiveSupport::TestCase
9
+ def setup
10
+ @author = Author.new(id: 1, name: 'Steve K.')
11
+ @author.bio = nil
12
+ @author.roles = []
13
+ @blog = Blog.new(id: 23, name: 'AMS Blog')
14
+ @post = Post.new(id: 42, title: 'New Post', body: 'Body')
15
+ @anonymous_post = Post.new(id: 43, title: 'Hello!!', body: 'Hello, world!!')
16
+ @comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
17
+ @post.comments = [@comment]
18
+ @post.blog = @blog
19
+ @anonymous_post.comments = []
20
+ @anonymous_post.blog = nil
21
+ @comment.post = @post
22
+ @comment.author = nil
23
+ @post.author = @author
24
+ @anonymous_post.author = nil
25
+ @blog = Blog.new(id: 1, name: 'My Blog!!')
26
+ @blog.writer = @author
27
+ @blog.articles = [@post, @anonymous_post]
28
+ @author.posts = []
29
+ end
30
+
31
+ def test_toplevel_jsonapi_defaults_to_false
32
+ assert_equal config.fetch(:jsonapi_include_toplevel_object), false
33
+ end
34
+
35
+ def test_disable_toplevel_jsonapi
36
+ with_config(jsonapi_include_toplevel_object: false) do
37
+ hash = serialize(@post)
38
+ assert_nil(hash[:jsonapi])
39
+ end
40
+ end
41
+
42
+ def test_enable_toplevel_jsonapi
43
+ with_config(jsonapi_include_toplevel_object: true) do
44
+ hash = serialize(@post)
45
+ refute_nil(hash[:jsonapi])
46
+ end
47
+ end
48
+
49
+ def test_default_toplevel_jsonapi_version
50
+ with_config(jsonapi_include_toplevel_object: true) do
51
+ hash = serialize(@post)
52
+ assert_equal('1.0', hash[:jsonapi][:version])
53
+ end
54
+ end
55
+
56
+ def test_toplevel_jsonapi_no_meta
57
+ with_config(jsonapi_include_toplevel_object: true) do
58
+ hash = serialize(@post)
59
+ assert_nil(hash[:jsonapi][:meta])
60
+ end
61
+ end
62
+
63
+ def test_toplevel_jsonapi_meta
64
+ new_config = {
65
+ jsonapi_include_toplevel_object: true,
66
+ jsonapi_toplevel_meta: {
67
+ 'copyright' => 'Copyright 2015 Example Corp.'
68
+ }
69
+ }
70
+ with_config(new_config) do
71
+ hash = serialize(@post)
72
+ assert_equal(new_config[:jsonapi_toplevel_meta], hash.fetch(:jsonapi).fetch(:meta))
73
+ end
74
+ end
75
+
76
+ private
77
+
78
+ def serialize(resource, options = {})
79
+ serializable(resource, { adapter: :json_api }.merge!(options)).serializable_hash
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,514 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ module ActiveModelSerializers
6
+ module Adapter
7
+ class JsonApi
8
+ class KeyCaseTest < ActiveSupport::TestCase
9
+ class Post < ::Model
10
+ attributes :title, :body, :publish_at
11
+ associations :author, :comments
12
+ end
13
+ class Author < ::Model
14
+ attributes :first_name, :last_name
15
+ end
16
+ class Comment < ::Model
17
+ attributes :body
18
+ associations :author, :post
19
+ end
20
+
21
+ class PostSerializer < ActiveModel::Serializer
22
+ type 'posts'
23
+ attributes :title, :body, :publish_at
24
+ belongs_to :author
25
+ has_many :comments
26
+
27
+ link(:self) { post_url(object.id) }
28
+ link(:post_authors) { post_authors_url(object.id) }
29
+ link(:subscriber_comments) { post_comments_url(object.id) }
30
+
31
+ meta do
32
+ {
33
+ rating: 5,
34
+ favorite_count: 10
35
+ }
36
+ end
37
+ end
38
+
39
+ class AuthorSerializer < ActiveModel::Serializer
40
+ type 'authors'
41
+ attributes :first_name, :last_name
42
+ end
43
+
44
+ class CommentSerializer < ActiveModel::Serializer
45
+ type 'comments'
46
+ attributes :body
47
+ belongs_to :author
48
+ end
49
+
50
+ def mock_request(transform = nil)
51
+ context = Minitest::Mock.new
52
+ context.expect(:request_url, URI)
53
+ context.expect(:query_parameters, {})
54
+ context.expect(:url_helpers, Rails.application.routes.url_helpers)
55
+ @options = {}
56
+ @options[:key_transform] = transform if transform
57
+ @options[:serialization_context] = context
58
+ end
59
+
60
+ def setup
61
+ Rails.application.routes.draw do
62
+ resources :posts do
63
+ resources :authors
64
+ resources :comments
65
+ end
66
+ end
67
+ @publish_at = 1.day.from_now
68
+ @author = Author.new(id: 1, first_name: 'Bob', last_name: 'Jones')
69
+ @comment1 = Comment.new(id: 7, body: 'cool', author: @author)
70
+ @comment2 = Comment.new(id: 12, body: 'awesome', author: @author)
71
+ @post = Post.new(id: 1337, title: 'Title 1', body: 'Body 1',
72
+ author: @author, comments: [@comment1, @comment2],
73
+ publish_at: @publish_at)
74
+ @comment1.post = @post
75
+ @comment2.post = @post
76
+ end
77
+
78
+ def test_success_document_transform_default
79
+ mock_request
80
+ serializer = PostSerializer.new(@post)
81
+ adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer, @options)
82
+ result = adapter.serializable_hash
83
+ assert_equal({
84
+ data: {
85
+ id: '1337',
86
+ type: 'posts',
87
+ attributes: {
88
+ title: 'Title 1',
89
+ body: 'Body 1',
90
+ :"publish-at" => @publish_at
91
+ },
92
+ relationships: {
93
+ author: {
94
+ data: { id: '1', type: 'authors' }
95
+ },
96
+ comments: {
97
+ data: [
98
+ { id: '7', type: 'comments' },
99
+ { id: '12', type: 'comments' }
100
+ ]
101
+ }
102
+ },
103
+ links: {
104
+ self: 'http://example.com/posts/1337',
105
+ :"post-authors" => 'http://example.com/posts/1337/authors',
106
+ :"subscriber-comments" => 'http://example.com/posts/1337/comments'
107
+ },
108
+ meta: { rating: 5, :"favorite-count" => 10 }
109
+ }
110
+ }, result)
111
+ end
112
+
113
+ def test_success_document_transform_global_config
114
+ mock_request
115
+ result = with_config(key_transform: :camel_lower) do
116
+ serializer = PostSerializer.new(@post)
117
+ adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer, @options)
118
+ adapter.serializable_hash
119
+ end
120
+ assert_equal({
121
+ data: {
122
+ id: '1337',
123
+ type: 'posts',
124
+ attributes: {
125
+ title: 'Title 1',
126
+ body: 'Body 1',
127
+ publishAt: @publish_at
128
+ },
129
+ relationships: {
130
+ author: {
131
+ data: { id: '1', type: 'authors' }
132
+ },
133
+ comments: {
134
+ data: [
135
+ { id: '7', type: 'comments' },
136
+ { id: '12', type: 'comments' }
137
+ ]
138
+ }
139
+ },
140
+ links: {
141
+ self: 'http://example.com/posts/1337',
142
+ postAuthors: 'http://example.com/posts/1337/authors',
143
+ subscriberComments: 'http://example.com/posts/1337/comments'
144
+ },
145
+ meta: { rating: 5, favoriteCount: 10 }
146
+ }
147
+ }, result)
148
+ end
149
+
150
+ def test_success_doc_transform_serialization_ctx_overrides_global
151
+ mock_request(:camel)
152
+ result = with_config(key_transform: :camel_lower) do
153
+ serializer = PostSerializer.new(@post)
154
+ adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer, @options)
155
+ adapter.serializable_hash
156
+ end
157
+ assert_equal({
158
+ Data: {
159
+ Id: '1337',
160
+ Type: 'Posts',
161
+ Attributes: {
162
+ Title: 'Title 1',
163
+ Body: 'Body 1',
164
+ PublishAt: @publish_at
165
+ },
166
+ Relationships: {
167
+ Author: {
168
+ Data: { Id: '1', Type: 'Authors' }
169
+ },
170
+ Comments: {
171
+ Data: [
172
+ { Id: '7', Type: 'Comments' },
173
+ { Id: '12', Type: 'Comments' }
174
+ ]
175
+ }
176
+ },
177
+ Links: {
178
+ Self: 'http://example.com/posts/1337',
179
+ PostAuthors: 'http://example.com/posts/1337/authors',
180
+ SubscriberComments: 'http://example.com/posts/1337/comments'
181
+ },
182
+ Meta: { Rating: 5, FavoriteCount: 10 }
183
+ }
184
+ }, result)
185
+ end
186
+
187
+ def test_success_document_transform_dash
188
+ mock_request(:dash)
189
+ serializer = PostSerializer.new(@post)
190
+ adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer, @options)
191
+ result = adapter.serializable_hash
192
+ assert_equal({
193
+ data: {
194
+ id: '1337',
195
+ type: 'posts',
196
+ attributes: {
197
+ title: 'Title 1',
198
+ body: 'Body 1',
199
+ :"publish-at" => @publish_at
200
+ },
201
+ relationships: {
202
+ author: {
203
+ data: { id: '1', type: 'authors' }
204
+ },
205
+ comments: {
206
+ data: [
207
+ { id: '7', type: 'comments' },
208
+ { id: '12', type: 'comments' }
209
+ ]
210
+ }
211
+ },
212
+ links: {
213
+ self: 'http://example.com/posts/1337',
214
+ :"post-authors" => 'http://example.com/posts/1337/authors',
215
+ :"subscriber-comments" => 'http://example.com/posts/1337/comments'
216
+ },
217
+ meta: { rating: 5, :"favorite-count" => 10 }
218
+ }
219
+ }, result)
220
+ end
221
+
222
+ def test_success_document_transform_unaltered
223
+ mock_request(:unaltered)
224
+ serializer = PostSerializer.new(@post)
225
+ adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer, @options)
226
+ result = adapter.serializable_hash
227
+ assert_equal({
228
+ data: {
229
+ id: '1337',
230
+ type: 'posts',
231
+ attributes: {
232
+ title: 'Title 1',
233
+ body: 'Body 1',
234
+ publish_at: @publish_at
235
+ },
236
+ relationships: {
237
+ author: {
238
+ data: { id: '1', type: 'authors' }
239
+ },
240
+ comments: {
241
+ data: [
242
+ { id: '7', type: 'comments' },
243
+ { id: '12', type: 'comments' }
244
+ ]
245
+ }
246
+ },
247
+ links: {
248
+ self: 'http://example.com/posts/1337',
249
+ post_authors: 'http://example.com/posts/1337/authors',
250
+ subscriber_comments: 'http://example.com/posts/1337/comments'
251
+ },
252
+ meta: { rating: 5, favorite_count: 10 }
253
+ }
254
+ }, result)
255
+ end
256
+
257
+ def test_success_document_transform_undefined
258
+ mock_request(:zoot)
259
+ serializer = PostSerializer.new(@post)
260
+ adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer, @options)
261
+ exception = assert_raises NoMethodError do
262
+ adapter.serializable_hash
263
+ end
264
+ assert_match(/undefined method.*zoot/, exception.message)
265
+ end
266
+
267
+ def test_success_document_transform_camel
268
+ mock_request(:camel)
269
+ serializer = PostSerializer.new(@post)
270
+ adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer, @options)
271
+ result = adapter.serializable_hash
272
+ assert_equal({
273
+ Data: {
274
+ Id: '1337',
275
+ Type: 'Posts',
276
+ Attributes: {
277
+ Title: 'Title 1',
278
+ Body: 'Body 1',
279
+ PublishAt: @publish_at
280
+ },
281
+ Relationships: {
282
+ Author: {
283
+ Data: { Id: '1', Type: 'Authors' }
284
+ },
285
+ Comments: {
286
+ Data: [
287
+ { Id: '7', Type: 'Comments' },
288
+ { Id: '12', Type: 'Comments' }
289
+ ]
290
+ }
291
+ },
292
+ Links: {
293
+ Self: 'http://example.com/posts/1337',
294
+ PostAuthors: 'http://example.com/posts/1337/authors',
295
+ SubscriberComments: 'http://example.com/posts/1337/comments'
296
+ },
297
+ Meta: { Rating: 5, FavoriteCount: 10 }
298
+ }
299
+ }, result)
300
+ end
301
+
302
+ def test_success_document_transform_camel_lower
303
+ mock_request(:camel_lower)
304
+ serializer = PostSerializer.new(@post)
305
+ adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer, @options)
306
+ result = adapter.serializable_hash
307
+ assert_equal({
308
+ data: {
309
+ id: '1337',
310
+ type: 'posts',
311
+ attributes: {
312
+ title: 'Title 1',
313
+ body: 'Body 1',
314
+ publishAt: @publish_at
315
+ },
316
+ relationships: {
317
+ author: {
318
+ data: { id: '1', type: 'authors' }
319
+ },
320
+ comments: {
321
+ data: [
322
+ { id: '7', type: 'comments' },
323
+ { id: '12', type: 'comments' }
324
+ ]
325
+ }
326
+ },
327
+ links: {
328
+ self: 'http://example.com/posts/1337',
329
+ postAuthors: 'http://example.com/posts/1337/authors',
330
+ subscriberComments: 'http://example.com/posts/1337/comments'
331
+ },
332
+ meta: { rating: 5, favoriteCount: 10 }
333
+ }
334
+ }, result)
335
+ end
336
+
337
+ def test_error_document_transform_default
338
+ mock_request
339
+ resource = ModelWithErrors.new
340
+ resource.errors.add(:published_at, 'must be in the future')
341
+ resource.errors.add(:title, 'must be longer')
342
+ serializer = ActiveModel::Serializer::ErrorSerializer.new(resource)
343
+ adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer, @options)
344
+ result = adapter.serializable_hash
345
+ expected_errors_object = {
346
+ errors: [
347
+ {
348
+ source: { pointer: '/data/attributes/published-at' },
349
+ detail: 'must be in the future'
350
+ },
351
+ {
352
+ source: { pointer: '/data/attributes/title' },
353
+ detail: 'must be longer'
354
+ }
355
+ ]
356
+ }
357
+ assert_equal expected_errors_object, result
358
+ end
359
+
360
+ def test_error_document_transform_global_config
361
+ mock_request
362
+ result = with_config(key_transform: :camel) do
363
+ resource = ModelWithErrors.new
364
+ resource.errors.add(:published_at, 'must be in the future')
365
+ resource.errors.add(:title, 'must be longer')
366
+ serializer = ActiveModel::Serializer::ErrorSerializer.new(resource)
367
+ adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer, @options)
368
+ adapter.serializable_hash
369
+ end
370
+ expected_errors_object = {
371
+ Errors: [
372
+ {
373
+ Source: { Pointer: '/data/attributes/PublishedAt' },
374
+ Detail: 'must be in the future'
375
+ },
376
+ {
377
+ Source: { Pointer: '/data/attributes/Title' },
378
+ Detail: 'must be longer'
379
+ }
380
+ ]
381
+ }
382
+ assert_equal expected_errors_object, result
383
+ end
384
+
385
+ def test_error_document_transform_serialization_ctx_overrides_global
386
+ mock_request(:camel)
387
+ result = with_config(key_transform: :camel_lower) do
388
+ resource = ModelWithErrors.new
389
+ resource.errors.add(:published_at, 'must be in the future')
390
+ resource.errors.add(:title, 'must be longer')
391
+ serializer = ActiveModel::Serializer::ErrorSerializer.new(resource)
392
+ adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer, @options)
393
+ adapter.serializable_hash
394
+ end
395
+ expected_errors_object = {
396
+ Errors: [
397
+ {
398
+ Source: { Pointer: '/data/attributes/PublishedAt' },
399
+ Detail: 'must be in the future'
400
+ },
401
+ {
402
+ Source: { Pointer: '/data/attributes/Title' },
403
+ Detail: 'must be longer'
404
+ }
405
+ ]
406
+ }
407
+ assert_equal expected_errors_object, result
408
+ end
409
+
410
+ def test_error_document_transform_dash
411
+ mock_request(:dash)
412
+
413
+ resource = ModelWithErrors.new
414
+ resource.errors.add(:published_at, 'must be in the future')
415
+ resource.errors.add(:title, 'must be longer')
416
+
417
+ serializer = ActiveModel::Serializer::ErrorSerializer.new(resource)
418
+ adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer, @options)
419
+ result = adapter.serializable_hash
420
+
421
+ expected_errors_object = {
422
+ errors: [
423
+ {
424
+ source: { pointer: '/data/attributes/published-at' },
425
+ detail: 'must be in the future'
426
+ },
427
+ {
428
+ source: { pointer: '/data/attributes/title' },
429
+ detail: 'must be longer'
430
+ }
431
+ ]
432
+ }
433
+ assert_equal expected_errors_object, result
434
+ end
435
+
436
+ def test_error_document_transform_unaltered
437
+ mock_request(:unaltered)
438
+
439
+ resource = ModelWithErrors.new
440
+ resource.errors.add(:published_at, 'must be in the future')
441
+ resource.errors.add(:title, 'must be longer')
442
+
443
+ serializer = ActiveModel::Serializer::ErrorSerializer.new(resource)
444
+ adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer, @options)
445
+ result = adapter.serializable_hash
446
+
447
+ expected_errors_object = {
448
+ errors: [
449
+ { source: { pointer: '/data/attributes/published_at' }, detail: 'must be in the future' },
450
+ { source: { pointer: '/data/attributes/title' }, detail: 'must be longer' }
451
+ ]
452
+ }
453
+ assert_equal expected_errors_object, result
454
+ end
455
+
456
+ def test_error_document_transform_undefined
457
+ mock_request(:krazy)
458
+
459
+ resource = ModelWithErrors.new
460
+ resource.errors.add(:published_at, 'must be in the future')
461
+ resource.errors.add(:title, 'must be longer')
462
+
463
+ serializer = ActiveModel::Serializer::ErrorSerializer.new(resource)
464
+ adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer, @options)
465
+
466
+ exception = assert_raises NoMethodError do
467
+ adapter.serializable_hash
468
+ end
469
+ assert_match(/undefined method.*krazy/, exception.message)
470
+ end
471
+
472
+ def test_error_document_transform_camel
473
+ mock_request(:camel)
474
+
475
+ resource = ModelWithErrors.new
476
+ resource.errors.add(:published_at, 'must be in the future')
477
+ resource.errors.add(:title, 'must be longer')
478
+
479
+ serializer = ActiveModel::Serializer::ErrorSerializer.new(resource)
480
+ adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer, @options)
481
+ result = adapter.serializable_hash
482
+
483
+ expected_errors_object = {
484
+ Errors: [
485
+ { Source: { Pointer: '/data/attributes/PublishedAt' }, Detail: 'must be in the future' },
486
+ { Source: { Pointer: '/data/attributes/Title' }, Detail: 'must be longer' }
487
+ ]
488
+ }
489
+ assert_equal expected_errors_object, result
490
+ end
491
+
492
+ def test_error_document_transform_camel_lower
493
+ mock_request(:camel_lower)
494
+
495
+ resource = ModelWithErrors.new
496
+ resource.errors.add(:published_at, 'must be in the future')
497
+ resource.errors.add(:title, 'must be longer')
498
+
499
+ serializer = ActiveModel::Serializer::ErrorSerializer.new(resource)
500
+ adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer, @options)
501
+ result = adapter.serializable_hash
502
+
503
+ expected_errors_object = {
504
+ errors: [
505
+ { source: { pointer: '/data/attributes/publishedAt' }, detail: 'must be in the future' },
506
+ { source: { pointer: '/data/attributes/title' }, detail: 'must be longer' }
507
+ ]
508
+ }
509
+ assert_equal expected_errors_object, result
510
+ end
511
+ end
512
+ end
513
+ end
514
+ end