active_model_serializers 0.8.3 → 0.10.0

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 (232) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE.md +29 -0
  3. data/.github/PULL_REQUEST_TEMPLATE.md +15 -0
  4. data/.gitignore +17 -0
  5. data/.rubocop.yml +104 -0
  6. data/.rubocop_todo.yml +167 -0
  7. data/.simplecov +110 -0
  8. data/.travis.yml +39 -24
  9. data/CHANGELOG.md +465 -6
  10. data/CONTRIBUTING.md +105 -0
  11. data/Gemfile +50 -1
  12. data/{MIT-LICENSE.txt → MIT-LICENSE} +3 -2
  13. data/README.md +102 -590
  14. data/Rakefile +93 -8
  15. data/active_model_serializers.gemspec +65 -23
  16. data/appveyor.yml +24 -0
  17. data/bin/bench +171 -0
  18. data/bin/bench_regression +316 -0
  19. data/bin/serve_benchmark +39 -0
  20. data/docs/ARCHITECTURE.md +126 -0
  21. data/docs/README.md +40 -0
  22. data/docs/STYLE.md +58 -0
  23. data/docs/general/adapters.md +245 -0
  24. data/docs/general/caching.md +52 -0
  25. data/docs/general/configuration_options.md +100 -0
  26. data/docs/general/deserialization.md +100 -0
  27. data/docs/general/getting_started.md +133 -0
  28. data/docs/general/instrumentation.md +40 -0
  29. data/docs/general/key_transforms.md +40 -0
  30. data/docs/general/logging.md +14 -0
  31. data/docs/general/rendering.md +255 -0
  32. data/docs/general/serializers.md +372 -0
  33. data/docs/how-open-source-maintained.jpg +0 -0
  34. data/docs/howto/add_pagination_links.md +139 -0
  35. data/docs/howto/add_root_key.md +51 -0
  36. data/docs/howto/outside_controller_use.md +58 -0
  37. data/docs/howto/passing_arbitrary_options.md +27 -0
  38. data/docs/howto/serialize_poro.md +32 -0
  39. data/docs/howto/test.md +152 -0
  40. data/docs/integrations/ember-and-json-api.md +112 -0
  41. data/docs/integrations/grape.md +19 -0
  42. data/docs/jsonapi/errors.md +56 -0
  43. data/docs/jsonapi/schema/schema.json +366 -0
  44. data/docs/jsonapi/schema.md +151 -0
  45. data/docs/rfcs/0000-namespace.md +106 -0
  46. data/docs/rfcs/template.md +15 -0
  47. data/lib/action_controller/serialization.rb +31 -36
  48. data/lib/active_model/serializable_resource.rb +11 -0
  49. data/lib/active_model/serializer/adapter/attributes.rb +15 -0
  50. data/lib/active_model/serializer/adapter/base.rb +16 -0
  51. data/lib/active_model/serializer/adapter/json.rb +15 -0
  52. data/lib/active_model/serializer/adapter/json_api.rb +15 -0
  53. data/lib/active_model/serializer/adapter/null.rb +15 -0
  54. data/lib/active_model/serializer/adapter.rb +24 -0
  55. data/lib/active_model/serializer/array_serializer.rb +9 -0
  56. data/lib/active_model/serializer/association.rb +19 -0
  57. data/lib/active_model/serializer/associations.rb +87 -220
  58. data/lib/active_model/serializer/attribute.rb +25 -0
  59. data/lib/active_model/serializer/attributes.rb +82 -0
  60. data/lib/active_model/serializer/belongs_to_reflection.rb +10 -0
  61. data/lib/active_model/serializer/caching.rb +333 -0
  62. data/lib/active_model/serializer/collection_reflection.rb +7 -0
  63. data/lib/active_model/serializer/collection_serializer.rb +64 -0
  64. data/lib/active_model/serializer/configuration.rb +35 -0
  65. data/lib/active_model/serializer/error_serializer.rb +10 -0
  66. data/lib/active_model/serializer/errors_serializer.rb +27 -0
  67. data/lib/active_model/serializer/field.rb +90 -0
  68. data/lib/active_model/serializer/fieldset.rb +31 -0
  69. data/lib/active_model/serializer/has_many_reflection.rb +10 -0
  70. data/lib/active_model/serializer/has_one_reflection.rb +10 -0
  71. data/lib/active_model/serializer/include_tree.rb +111 -0
  72. data/lib/active_model/serializer/links.rb +35 -0
  73. data/lib/active_model/serializer/lint.rb +146 -0
  74. data/lib/active_model/serializer/meta.rb +29 -0
  75. data/lib/active_model/serializer/null.rb +17 -0
  76. data/lib/active_model/serializer/reflection.rb +147 -0
  77. data/lib/active_model/serializer/singular_reflection.rb +7 -0
  78. data/lib/active_model/serializer/type.rb +25 -0
  79. data/lib/active_model/{serializers → serializer}/version.rb +1 -1
  80. data/lib/active_model/serializer.rb +158 -481
  81. data/lib/active_model_serializers/adapter/attributes.rb +76 -0
  82. data/lib/active_model_serializers/adapter/base.rb +83 -0
  83. data/lib/active_model_serializers/adapter/json.rb +21 -0
  84. data/lib/active_model_serializers/adapter/json_api/deserialization.rb +213 -0
  85. data/lib/active_model_serializers/adapter/json_api/error.rb +96 -0
  86. data/lib/active_model_serializers/adapter/json_api/jsonapi.rb +49 -0
  87. data/lib/active_model_serializers/adapter/json_api/link.rb +83 -0
  88. data/lib/active_model_serializers/adapter/json_api/meta.rb +37 -0
  89. data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +62 -0
  90. data/lib/active_model_serializers/adapter/json_api/relationship.rb +52 -0
  91. data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +37 -0
  92. data/lib/active_model_serializers/adapter/json_api.rb +516 -0
  93. data/lib/active_model_serializers/adapter/null.rb +9 -0
  94. data/lib/active_model_serializers/adapter.rb +92 -0
  95. data/lib/active_model_serializers/callbacks.rb +55 -0
  96. data/lib/active_model_serializers/deprecate.rb +55 -0
  97. data/lib/active_model_serializers/deserialization.rb +13 -0
  98. data/lib/active_model_serializers/json_pointer.rb +14 -0
  99. data/lib/active_model_serializers/key_transform.rb +70 -0
  100. data/lib/active_model_serializers/logging.rb +122 -0
  101. data/lib/active_model_serializers/model.rb +49 -0
  102. data/lib/active_model_serializers/railtie.rb +46 -0
  103. data/lib/active_model_serializers/register_jsonapi_renderer.rb +65 -0
  104. data/lib/active_model_serializers/serializable_resource.rb +81 -0
  105. data/lib/active_model_serializers/serialization_context.rb +32 -0
  106. data/lib/active_model_serializers/test/schema.rb +138 -0
  107. data/lib/active_model_serializers/test/serializer.rb +125 -0
  108. data/lib/active_model_serializers/test.rb +7 -0
  109. data/lib/active_model_serializers.rb +32 -89
  110. data/lib/generators/rails/USAGE +6 -0
  111. data/lib/generators/rails/resource_override.rb +10 -0
  112. data/lib/generators/rails/serializer_generator.rb +36 -0
  113. data/lib/generators/rails/templates/serializer.rb.erb +8 -0
  114. data/lib/grape/active_model_serializers.rb +14 -0
  115. data/lib/grape/formatters/active_model_serializers.rb +15 -0
  116. data/lib/grape/helpers/active_model_serializers.rb +16 -0
  117. data/test/action_controller/adapter_selector_test.rb +53 -0
  118. data/test/action_controller/explicit_serializer_test.rb +134 -0
  119. data/test/action_controller/json/include_test.rb +167 -0
  120. data/test/action_controller/json_api/deserialization_test.rb +112 -0
  121. data/test/action_controller/json_api/errors_test.rb +41 -0
  122. data/test/action_controller/json_api/linked_test.rb +197 -0
  123. data/test/action_controller/json_api/pagination_test.rb +116 -0
  124. data/test/action_controller/json_api/transform_test.rb +181 -0
  125. data/test/action_controller/serialization_scope_name_test.rb +229 -0
  126. data/test/action_controller/serialization_test.rb +469 -0
  127. data/test/active_model_serializers/adapter_for_test.rb +208 -0
  128. data/test/active_model_serializers/json_pointer_test.rb +20 -0
  129. data/test/active_model_serializers/key_transform_test.rb +263 -0
  130. data/test/active_model_serializers/logging_test.rb +77 -0
  131. data/test/active_model_serializers/model_test.rb +9 -0
  132. data/test/active_model_serializers/railtie_test_isolated.rb +63 -0
  133. data/test/active_model_serializers/serialization_context_test_isolated.rb +58 -0
  134. data/test/active_model_serializers/test/schema_test.rb +130 -0
  135. data/test/active_model_serializers/test/serializer_test.rb +62 -0
  136. data/test/active_record_test.rb +9 -0
  137. data/test/adapter/deprecation_test.rb +100 -0
  138. data/test/adapter/json/belongs_to_test.rb +45 -0
  139. data/test/adapter/json/collection_test.rb +90 -0
  140. data/test/adapter/json/has_many_test.rb +45 -0
  141. data/test/adapter/json/transform_test.rb +93 -0
  142. data/test/adapter/json_api/belongs_to_test.rb +155 -0
  143. data/test/adapter/json_api/collection_test.rb +95 -0
  144. data/test/adapter/json_api/errors_test.rb +78 -0
  145. data/test/adapter/json_api/fields_test.rb +87 -0
  146. data/test/adapter/json_api/has_many_embed_ids_test.rb +43 -0
  147. data/test/adapter/json_api/has_many_explicit_serializer_test.rb +96 -0
  148. data/test/adapter/json_api/has_many_test.rb +144 -0
  149. data/test/adapter/json_api/has_one_test.rb +80 -0
  150. data/test/adapter/json_api/json_api_test.rb +35 -0
  151. data/test/adapter/json_api/linked_test.rb +392 -0
  152. data/test/adapter/json_api/links_test.rb +93 -0
  153. data/test/adapter/json_api/pagination_links_test.rb +166 -0
  154. data/test/adapter/json_api/parse_test.rb +137 -0
  155. data/test/adapter/json_api/relationship_test.rb +161 -0
  156. data/test/adapter/json_api/relationships_test.rb +199 -0
  157. data/test/adapter/json_api/resource_identifier_test.rb +85 -0
  158. data/test/adapter/json_api/resource_meta_test.rb +100 -0
  159. data/test/adapter/json_api/toplevel_jsonapi_test.rb +82 -0
  160. data/test/adapter/json_api/transform_test.rb +502 -0
  161. data/test/adapter/json_api/type_test.rb +61 -0
  162. data/test/adapter/json_test.rb +45 -0
  163. data/test/adapter/null_test.rb +23 -0
  164. data/test/adapter/polymorphic_test.rb +171 -0
  165. data/test/adapter_test.rb +67 -0
  166. data/test/array_serializer_test.rb +20 -73
  167. data/test/benchmark/app.rb +65 -0
  168. data/test/benchmark/benchmarking_support.rb +67 -0
  169. data/test/benchmark/bm_caching.rb +119 -0
  170. data/test/benchmark/bm_transform.rb +34 -0
  171. data/test/benchmark/config.ru +3 -0
  172. data/test/benchmark/controllers.rb +84 -0
  173. data/test/benchmark/fixtures.rb +219 -0
  174. data/test/cache_test.rb +485 -0
  175. data/test/collection_serializer_test.rb +110 -0
  176. data/test/fixtures/active_record.rb +78 -0
  177. data/test/fixtures/poro.rb +282 -0
  178. data/test/generators/scaffold_controller_generator_test.rb +24 -0
  179. data/test/generators/serializer_generator_test.rb +57 -0
  180. data/test/grape_test.rb +82 -0
  181. data/test/include_tree/from_include_args_test.rb +26 -0
  182. data/test/include_tree/from_string_test.rb +94 -0
  183. data/test/include_tree/include_args_to_hash_test.rb +64 -0
  184. data/test/lint_test.rb +49 -0
  185. data/test/logger_test.rb +18 -0
  186. data/test/poro_test.rb +9 -0
  187. data/test/serializable_resource_test.rb +83 -0
  188. data/test/serializers/association_macros_test.rb +36 -0
  189. data/test/serializers/associations_test.rb +295 -0
  190. data/test/serializers/attribute_test.rb +151 -0
  191. data/test/serializers/attributes_test.rb +52 -0
  192. data/test/serializers/caching_configuration_test_isolated.rb +170 -0
  193. data/test/serializers/configuration_test.rb +32 -0
  194. data/test/serializers/fieldset_test.rb +14 -0
  195. data/test/serializers/meta_test.rb +196 -0
  196. data/test/serializers/options_test.rb +21 -0
  197. data/test/serializers/read_attribute_for_serialization_test.rb +79 -0
  198. data/test/serializers/root_test.rb +21 -0
  199. data/test/serializers/serialization_test.rb +55 -0
  200. data/test/serializers/serializer_for_test.rb +134 -0
  201. data/test/support/custom_schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
  202. data/test/support/isolated_unit.rb +79 -0
  203. data/test/support/rails5_shims.rb +47 -0
  204. data/test/support/rails_app.rb +45 -0
  205. data/test/support/schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
  206. data/test/support/schemas/active_model_serializers/test/schema_test/my/show.json +6 -0
  207. data/test/support/schemas/custom/show.json +7 -0
  208. data/test/support/schemas/hyper_schema.json +93 -0
  209. data/test/support/schemas/render_using_json_api.json +43 -0
  210. data/test/support/schemas/simple_json_pointers.json +10 -0
  211. data/test/support/serialization_testing.rb +53 -0
  212. data/test/test_helper.rb +48 -23
  213. metadata +449 -43
  214. data/DESIGN.textile +0 -586
  215. data/Gemfile.edge +0 -9
  216. data/bench/perf.rb +0 -43
  217. data/cruft.md +0 -19
  218. data/lib/active_model/array_serializer.rb +0 -104
  219. data/lib/active_record/serializer_override.rb +0 -16
  220. data/lib/generators/resource_override.rb +0 -13
  221. data/lib/generators/serializer/USAGE +0 -9
  222. data/lib/generators/serializer/serializer_generator.rb +0 -42
  223. data/lib/generators/serializer/templates/serializer.rb +0 -19
  224. data/test/association_test.rb +0 -592
  225. data/test/caching_test.rb +0 -96
  226. data/test/generators_test.rb +0 -85
  227. data/test/no_serialization_scope_test.rb +0 -34
  228. data/test/serialization_scope_name_test.rb +0 -67
  229. data/test/serialization_test.rb +0 -392
  230. data/test/serializer_support_test.rb +0 -51
  231. data/test/serializer_test.rb +0 -1465
  232. data/test/test_fakes.rb +0 -217
@@ -0,0 +1,137 @@
1
+ require 'test_helper'
2
+ module ActiveModelSerializers
3
+ module Adapter
4
+ class JsonApi
5
+ module Deserialization
6
+ class ParseTest < Minitest::Test
7
+ def setup
8
+ @hash = {
9
+ 'data' => {
10
+ 'type' => 'photos',
11
+ 'id' => 'zorglub',
12
+ 'attributes' => {
13
+ 'title' => 'Ember Hamster',
14
+ 'src' => 'http://example.com/images/productivity.png'
15
+ },
16
+ 'relationships' => {
17
+ 'author' => {
18
+ 'data' => nil
19
+ },
20
+ 'photographer' => {
21
+ 'data' => { 'type' => 'people', 'id' => '9' }
22
+ },
23
+ 'comments' => {
24
+ 'data' => [
25
+ { 'type' => 'comments', 'id' => '1' },
26
+ { 'type' => 'comments', 'id' => '2' }
27
+ ]
28
+ }
29
+ }
30
+ }
31
+ }
32
+ @params = ActionController::Parameters.new(@hash)
33
+ @expected = {
34
+ id: 'zorglub',
35
+ title: 'Ember Hamster',
36
+ src: 'http://example.com/images/productivity.png',
37
+ author_id: nil,
38
+ photographer_id: '9',
39
+ comment_ids: %w(1 2)
40
+ }
41
+
42
+ @illformed_payloads = [nil,
43
+ {},
44
+ {
45
+ 'data' => nil
46
+ }, {
47
+ 'data' => { 'attributes' => [] }
48
+ }, {
49
+ 'data' => { 'relationships' => [] }
50
+ }, {
51
+ 'data' => {
52
+ 'relationships' => { 'rel' => nil }
53
+ }
54
+ }, {
55
+ 'data' => {
56
+ 'relationships' => { 'rel' => {} }
57
+ }
58
+ }]
59
+ end
60
+
61
+ def test_hash
62
+ parsed_hash = ActiveModelSerializers::Adapter::JsonApi::Deserialization.parse!(@hash)
63
+ assert_equal(@expected, parsed_hash)
64
+ end
65
+
66
+ def test_actioncontroller_parameters
67
+ assert_equal(false, @params.permitted?)
68
+ parsed_hash = ActiveModelSerializers::Adapter::JsonApi::Deserialization.parse!(@params)
69
+ assert_equal(@expected, parsed_hash)
70
+ end
71
+
72
+ def test_illformed_payloads_safe
73
+ @illformed_payloads.each do |p|
74
+ parsed_hash = ActiveModelSerializers::Adapter::JsonApi::Deserialization.parse(p)
75
+ assert_equal({}, parsed_hash)
76
+ end
77
+ end
78
+
79
+ def test_illformed_payloads_unsafe
80
+ @illformed_payloads.each do |p|
81
+ assert_raises(InvalidDocument) do
82
+ ActiveModelSerializers::Adapter::JsonApi::Deserialization.parse!(p)
83
+ end
84
+ end
85
+ end
86
+
87
+ def test_filter_fields_only
88
+ parsed_hash = ActiveModelSerializers::Adapter::JsonApi::Deserialization.parse!(@hash, only: [:id, :title, :author])
89
+ expected = {
90
+ id: 'zorglub',
91
+ title: 'Ember Hamster',
92
+ author_id: nil
93
+ }
94
+ assert_equal(expected, parsed_hash)
95
+ end
96
+
97
+ def test_filter_fields_except
98
+ parsed_hash = ActiveModelSerializers::Adapter::JsonApi::Deserialization.parse!(@hash, except: [:id, :title, :author])
99
+ expected = {
100
+ src: 'http://example.com/images/productivity.png',
101
+ photographer_id: '9',
102
+ comment_ids: %w(1 2)
103
+ }
104
+ assert_equal(expected, parsed_hash)
105
+ end
106
+
107
+ def test_keys
108
+ parsed_hash = ActiveModelSerializers::Adapter::JsonApi::Deserialization.parse!(@hash, keys: { author: :user, title: :post_title })
109
+ expected = {
110
+ id: 'zorglub',
111
+ post_title: 'Ember Hamster',
112
+ src: 'http://example.com/images/productivity.png',
113
+ user_id: nil,
114
+ photographer_id: '9',
115
+ comment_ids: %w(1 2)
116
+ }
117
+ assert_equal(expected, parsed_hash)
118
+ end
119
+
120
+ def test_polymorphic
121
+ parsed_hash = ActiveModelSerializers::Adapter::JsonApi::Deserialization.parse!(@hash, polymorphic: [:photographer])
122
+ expected = {
123
+ id: 'zorglub',
124
+ title: 'Ember Hamster',
125
+ src: 'http://example.com/images/productivity.png',
126
+ author_id: nil,
127
+ photographer_id: '9',
128
+ photographer_type: 'people',
129
+ comment_ids: %w(1 2)
130
+ }
131
+ assert_equal(expected, parsed_hash)
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,161 @@
1
+ require 'test_helper'
2
+
3
+ module ActiveModelSerializers
4
+ module Adapter
5
+ class JsonApi
6
+ class RelationshipTest < ActiveSupport::TestCase
7
+ setup do
8
+ @blog = Blog.new(id: 1)
9
+ @author = Author.new(id: 1, name: 'Steve K.', blog: @blog)
10
+ @serializer = BlogSerializer.new(@blog)
11
+ ActionController::Base.cache_store.clear
12
+ end
13
+
14
+ def test_relationship_with_data
15
+ expected = {
16
+ data: {
17
+ id: '1',
18
+ type: 'blogs'
19
+ }
20
+ }
21
+ test_relationship(expected, options: { include_data: true })
22
+ end
23
+
24
+ def test_relationship_with_nil_model
25
+ @serializer = BlogSerializer.new(nil)
26
+ expected = { data: nil }
27
+ test_relationship(expected, options: { include_data: true })
28
+ end
29
+
30
+ def test_relationship_with_nil_serializer
31
+ @serializer = nil
32
+ expected = { data: nil }
33
+ test_relationship(expected, options: { include_data: true })
34
+ end
35
+
36
+ def test_relationship_with_data_array
37
+ posts = [Post.new(id: 1), Post.new(id: 2)]
38
+ @serializer = ActiveModel::Serializer::CollectionSerializer.new(posts)
39
+ @author.posts = posts
40
+ @author.blog = nil
41
+ expected = {
42
+ data: [
43
+ {
44
+ id: '1',
45
+ type: 'posts'
46
+ },
47
+ {
48
+ id: '2',
49
+ type: 'posts'
50
+ }
51
+ ]
52
+ }
53
+ test_relationship(expected, options: { include_data: true })
54
+ end
55
+
56
+ def test_relationship_data_not_included
57
+ test_relationship({}, options: { include_data: false })
58
+ end
59
+
60
+ def test_relationship_simple_link
61
+ links = { self: 'a link' }
62
+ test_relationship({ links: { self: 'a link' } }, links: links)
63
+ end
64
+
65
+ def test_relationship_many_links
66
+ links = {
67
+ self: 'a link',
68
+ related: 'another link'
69
+ }
70
+ expected = {
71
+ links: {
72
+ self: 'a link',
73
+ related: 'another link'
74
+ }
75
+ }
76
+ test_relationship(expected, links: links)
77
+ end
78
+
79
+ def test_relationship_block_link
80
+ links = { self: proc { object.id.to_s } }
81
+ expected = { links: { self: @blog.id.to_s } }
82
+ test_relationship(expected, links: links)
83
+ end
84
+
85
+ def test_relationship_block_link_with_meta
86
+ links = {
87
+ self: proc do
88
+ href object.id.to_s
89
+ meta(id: object.id)
90
+ end
91
+ }
92
+ expected = {
93
+ links: {
94
+ self: {
95
+ href: @blog.id.to_s,
96
+ meta: { id: @blog.id }
97
+ }
98
+ }
99
+ }
100
+ test_relationship(expected, links: links)
101
+ end
102
+
103
+ def test_relationship_simple_meta
104
+ meta = { id: '1' }
105
+ expected = { meta: meta }
106
+ test_relationship(expected, meta: meta)
107
+ end
108
+
109
+ def test_relationship_block_meta
110
+ meta = proc do
111
+ { id: object.id }
112
+ end
113
+ expected = {
114
+ meta: {
115
+ id: @blog.id
116
+ }
117
+ }
118
+ test_relationship(expected, meta: meta)
119
+ end
120
+
121
+ def test_relationship_with_everything
122
+ links = {
123
+ self: 'a link',
124
+ related: proc do
125
+ href object.id.to_s
126
+ meta object.id
127
+ end
128
+
129
+ }
130
+ meta = proc do
131
+ { id: object.id }
132
+ end
133
+ expected = {
134
+ data: {
135
+ id: '1',
136
+ type: 'blogs'
137
+ },
138
+ links: {
139
+ self: 'a link',
140
+ related: {
141
+ href: '1', meta: 1
142
+ }
143
+ },
144
+ meta: {
145
+ id: @blog.id
146
+ }
147
+ }
148
+ test_relationship(expected, meta: meta, options: { include_data: true }, links: links)
149
+ end
150
+
151
+ private
152
+
153
+ def test_relationship(expected, params = {})
154
+ parent_serializer = AuthorSerializer.new(@author)
155
+ relationship = Relationship.new(parent_serializer, @serializer, nil, params)
156
+ assert_equal(expected, relationship.as_json)
157
+ end
158
+ end
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,199 @@
1
+ require 'test_helper'
2
+
3
+ module ActiveModel
4
+ class Serializer
5
+ module Adapter
6
+ class JsonApi
7
+ class RelationshipTest < ActiveSupport::TestCase
8
+ RelationshipAuthor = Class.new(::Model)
9
+ class RelationshipAuthorSerializer < ActiveModel::Serializer
10
+ has_one :bio do
11
+ link :self, '//example.com/link_author/relationships/bio'
12
+ end
13
+
14
+ has_one :profile do
15
+ link :related do
16
+ "//example.com/profiles/#{object.profile.id}"
17
+ end
18
+ end
19
+
20
+ has_many :locations do
21
+ link :related do
22
+ ids = object.locations.map(&:id).join(',')
23
+ href "//example.com/locations/#{ids}"
24
+ end
25
+ end
26
+
27
+ has_many :posts do
28
+ link :related do
29
+ ids = object.posts.map(&:id).join(',')
30
+ href "//example.com/posts/#{ids}"
31
+ meta ids: ids
32
+ end
33
+ end
34
+
35
+ has_many :comments do
36
+ link :self do
37
+ meta ids: [1]
38
+ end
39
+ end
40
+
41
+ has_many :roles do |serializer|
42
+ meta count: object.posts.count
43
+ serializer.cached_roles
44
+ end
45
+
46
+ has_one :blog do
47
+ link :self, '//example.com/link_author/relationships/blog'
48
+ include_data false
49
+ end
50
+
51
+ belongs_to :reviewer do
52
+ meta name: 'Dan Brown'
53
+ include_data true
54
+ end
55
+
56
+ has_many :likes do
57
+ link :related do
58
+ ids = object.likes.map(&:id).join(',')
59
+ href "//example.com/likes/#{ids}"
60
+ meta ids: ids
61
+ end
62
+ meta liked: object.likes.any?
63
+ end
64
+
65
+ def cached_roles
66
+ [
67
+ Role.new(id: 'from-serializer-method')
68
+ ]
69
+ end
70
+ end
71
+
72
+ def setup
73
+ @post = Post.new(id: 1337, comments: [], author: nil)
74
+ @blog = Blog.new(id: 1337, name: 'extra')
75
+ @bio = Bio.new(id: 1337)
76
+ @like = Like.new(id: 1337)
77
+ @role = Role.new(id: 'from-record')
78
+ @profile = Profile.new(id: 1337)
79
+ @location = Location.new(id: 1337)
80
+ @reviewer = Author.new(id: 1337)
81
+ @comment = Comment.new(id: 1337)
82
+ @author = RelationshipAuthor.new(
83
+ id: 1337,
84
+ posts: [@post],
85
+ blog: @blog,
86
+ reviewer: @reviewer,
87
+ bio: @bio,
88
+ likes: [@like],
89
+ roles: [@role],
90
+ locations: [@location],
91
+ profile: @profile,
92
+ comments: [@comment]
93
+ )
94
+ end
95
+
96
+ def test_relationship_simple_link
97
+ expected = {
98
+ data: {
99
+ id: '1337',
100
+ type: 'bios'
101
+ },
102
+ links: {
103
+ self: '//example.com/link_author/relationships/bio'
104
+ }
105
+ }
106
+ assert_relationship(:bio, expected)
107
+ end
108
+
109
+ def test_relationship_block_link
110
+ expected = {
111
+ data: { id: '1337', type: 'profiles' },
112
+ links: { related: '//example.com/profiles/1337' }
113
+ }
114
+ assert_relationship(:profile, expected)
115
+ end
116
+
117
+ def test_relationship_block_link_href
118
+ expected = {
119
+ data: [{ id: '1337', type: 'locations' }],
120
+ links: {
121
+ related: { href: '//example.com/locations/1337' }
122
+ }
123
+ }
124
+ assert_relationship(:locations, expected)
125
+ end
126
+
127
+ def test_relationship_block_link_href_and_meta
128
+ expected = {
129
+ data: [{ id: '1337', type: 'posts' }],
130
+ links: {
131
+ related: {
132
+ href: '//example.com/posts/1337',
133
+ meta: { ids: '1337' }
134
+ }
135
+ }
136
+ }
137
+ assert_relationship(:posts, expected)
138
+ end
139
+
140
+ def test_relationship_block_link_meta
141
+ expected = {
142
+ data: [{ id: '1337', type: 'comments' }],
143
+ links: {
144
+ self: {
145
+ meta: { ids: [1] }
146
+ }
147
+ }
148
+ }
149
+ assert_relationship(:comments, expected)
150
+ end
151
+
152
+ def test_relationship_meta
153
+ expected = {
154
+ data: [{ id: 'from-serializer-method', type: 'roles' }],
155
+ meta: { count: 1 }
156
+ }
157
+ assert_relationship(:roles, expected)
158
+ end
159
+
160
+ def test_relationship_not_including_data
161
+ expected = {
162
+ links: { self: '//example.com/link_author/relationships/blog' }
163
+ }
164
+ assert_relationship(:blog, expected)
165
+ end
166
+
167
+ def test_relationship_including_data_explicit
168
+ expected = {
169
+ data: { id: '1337', type: 'authors' },
170
+ meta: { name: 'Dan Brown' }
171
+ }
172
+ assert_relationship(:reviewer, expected)
173
+ end
174
+
175
+ def test_relationship_with_everything
176
+ expected = {
177
+ data: [{ id: '1337', type: 'likes' }],
178
+ links: {
179
+ related: {
180
+ href: '//example.com/likes/1337',
181
+ meta: { ids: '1337' }
182
+ }
183
+ },
184
+ meta: { liked: true }
185
+ }
186
+ assert_relationship(:likes, expected)
187
+ end
188
+
189
+ private
190
+
191
+ def assert_relationship(relationship_name, expected)
192
+ hash = serializable(@author, adapter: :json_api).serializable_hash
193
+ assert_equal(expected, hash[:data][:relationships][relationship_name])
194
+ end
195
+ end
196
+ end
197
+ end
198
+ end
199
+ end
@@ -0,0 +1,85 @@
1
+ require 'test_helper'
2
+
3
+ module ActiveModelSerializers
4
+ module Adapter
5
+ class JsonApi
6
+ class ResourceIdentifierTest < ActiveSupport::TestCase
7
+ class WithDefinedTypeSerializer < ActiveModel::Serializer
8
+ type 'with_defined_type'
9
+ end
10
+
11
+ class WithDefinedIdSerializer < ActiveModel::Serializer
12
+ def id
13
+ 'special_id'
14
+ end
15
+ end
16
+
17
+ class FragmentedSerializer < ActiveModel::Serializer; end
18
+
19
+ setup do
20
+ @model = Author.new(id: 1, name: 'Steve K.')
21
+ ActionController::Base.cache_store.clear
22
+ end
23
+
24
+ def test_defined_type
25
+ test_type(WithDefinedTypeSerializer, 'with-defined-type')
26
+ end
27
+
28
+ def test_singular_type
29
+ test_type_inflection(AuthorSerializer, 'author', :singular)
30
+ end
31
+
32
+ def test_plural_type
33
+ test_type_inflection(AuthorSerializer, 'authors', :plural)
34
+ end
35
+
36
+ def test_id_defined_on_object
37
+ test_id(AuthorSerializer, @model.id.to_s)
38
+ end
39
+
40
+ def test_id_defined_on_serializer
41
+ test_id(WithDefinedIdSerializer, 'special_id')
42
+ end
43
+
44
+ def test_id_defined_on_fragmented
45
+ FragmentedSerializer.fragmented(WithDefinedIdSerializer.new(@model))
46
+ test_id(FragmentedSerializer, 'special_id')
47
+ end
48
+
49
+ private
50
+
51
+ def test_type_inflection(serializer_class, expected_type, inflection)
52
+ original_inflection = ActiveModelSerializers.config.jsonapi_resource_type
53
+ ActiveModelSerializers.config.jsonapi_resource_type = inflection
54
+ test_type(serializer_class, expected_type)
55
+ ensure
56
+ ActiveModelSerializers.config.jsonapi_resource_type = original_inflection
57
+ end
58
+
59
+ def test_type(serializer_class, expected_type)
60
+ serializer = serializer_class.new(@model)
61
+ resource_identifier = ResourceIdentifier.new(serializer, nil)
62
+ expected = {
63
+ id: @model.id.to_s,
64
+ type: expected_type
65
+ }
66
+
67
+ assert_equal(expected, resource_identifier.as_json)
68
+ end
69
+
70
+ def test_id(serializer_class, id)
71
+ serializer = serializer_class.new(@model)
72
+ resource_identifier = ResourceIdentifier.new(serializer, nil)
73
+ inflection = ActiveModelSerializers.config.jsonapi_resource_type
74
+ type = @model.class.model_name.send(inflection)
75
+ expected = {
76
+ id: id,
77
+ type: type
78
+ }
79
+
80
+ assert_equal(expected, resource_identifier.as_json)
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,100 @@
1
+ require 'test_helper'
2
+
3
+ module ActiveModel
4
+ class Serializer
5
+ module Adapter
6
+ class JsonApi
7
+ class ResourceMetaTest < Minitest::Test
8
+ class MetaHashPostSerializer < ActiveModel::Serializer
9
+ attributes :id
10
+ meta stuff: 'value'
11
+ end
12
+
13
+ class MetaBlockPostSerializer < ActiveModel::Serializer
14
+ attributes :id
15
+ meta do
16
+ { comments_count: object.comments.count }
17
+ end
18
+ end
19
+
20
+ class MetaBlockPostBlankMetaSerializer < ActiveModel::Serializer
21
+ attributes :id
22
+ meta do
23
+ {}
24
+ end
25
+ end
26
+
27
+ class MetaBlockPostEmptyStringSerializer < ActiveModel::Serializer
28
+ attributes :id
29
+ meta do
30
+ ''
31
+ end
32
+ end
33
+
34
+ def setup
35
+ @post = Post.new(id: 1337, comments: [], author: nil)
36
+ end
37
+
38
+ def test_meta_hash_object_resource
39
+ hash = ActiveModelSerializers::SerializableResource.new(
40
+ @post,
41
+ serializer: MetaHashPostSerializer,
42
+ adapter: :json_api
43
+ ).serializable_hash
44
+ expected = {
45
+ stuff: 'value'
46
+ }
47
+ assert_equal(expected, hash[:data][:meta])
48
+ end
49
+
50
+ def test_meta_block_object_resource
51
+ hash = ActiveModelSerializers::SerializableResource.new(
52
+ @post,
53
+ serializer: MetaBlockPostSerializer,
54
+ adapter: :json_api
55
+ ).serializable_hash
56
+ expected = {
57
+ :"comments-count" => @post.comments.count
58
+ }
59
+ assert_equal(expected, hash[:data][:meta])
60
+ end
61
+
62
+ def test_meta_object_resource_in_array
63
+ post2 = Post.new(id: 1339, comments: [Comment.new])
64
+ posts = [@post, post2]
65
+ hash = ActiveModelSerializers::SerializableResource.new(
66
+ posts,
67
+ each_serializer: MetaBlockPostSerializer,
68
+ adapter: :json_api
69
+ ).serializable_hash
70
+ expected = {
71
+ :data => [
72
+ { :id => '1337', :type => 'posts', :meta => { :"comments-count" => 0 } },
73
+ { :id => '1339', :type => 'posts', :meta => { :"comments-count" => 1 } }
74
+ ]
75
+ }
76
+ assert_equal(expected, hash)
77
+ end
78
+
79
+ def test_meta_object_blank_omitted
80
+ hash = ActiveModelSerializers::SerializableResource.new(
81
+ @post,
82
+ serializer: MetaBlockPostBlankMetaSerializer,
83
+ adapter: :json_api
84
+ ).serializable_hash
85
+ refute hash[:data].key? :meta
86
+ end
87
+
88
+ def test_meta_object_empty_string_omitted
89
+ hash = ActiveModelSerializers::SerializableResource.new(
90
+ @post,
91
+ serializer: MetaBlockPostEmptyStringSerializer,
92
+ adapter: :json_api
93
+ ).serializable_hash
94
+ refute hash[:data].key? :meta
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end