active_model_serializers 0.10.0 → 0.10.9

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 (206) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +10 -5
  3. data/.travis.yml +41 -21
  4. data/CHANGELOG.md +200 -2
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +25 -4
  7. data/README.md +166 -28
  8. data/Rakefile +5 -32
  9. data/active_model_serializers.gemspec +23 -25
  10. data/appveyor.yml +10 -6
  11. data/bin/rubocop +38 -0
  12. data/docs/README.md +2 -1
  13. data/docs/general/adapters.md +35 -11
  14. data/docs/general/caching.md +7 -1
  15. data/docs/general/configuration_options.md +86 -1
  16. data/docs/general/deserialization.md +1 -1
  17. data/docs/general/fields.md +31 -0
  18. data/docs/general/getting_started.md +1 -1
  19. data/docs/general/logging.md +7 -0
  20. data/docs/general/rendering.md +63 -25
  21. data/docs/general/serializers.md +137 -14
  22. data/docs/howto/add_pagination_links.md +16 -17
  23. data/docs/howto/add_relationship_links.md +140 -0
  24. data/docs/howto/add_root_key.md +11 -0
  25. data/docs/howto/grape_integration.md +42 -0
  26. data/docs/howto/outside_controller_use.md +12 -4
  27. data/docs/howto/passing_arbitrary_options.md +2 -2
  28. data/docs/howto/serialize_poro.md +46 -5
  29. data/docs/howto/test.md +2 -0
  30. data/docs/howto/upgrade_from_0_8_to_0_10.md +265 -0
  31. data/docs/integrations/ember-and-json-api.md +67 -32
  32. data/docs/jsonapi/schema.md +1 -1
  33. data/lib/action_controller/serialization.rb +15 -3
  34. data/lib/active_model/serializable_resource.rb +2 -0
  35. data/lib/active_model/serializer/adapter/attributes.rb +2 -0
  36. data/lib/active_model/serializer/adapter/base.rb +4 -0
  37. data/lib/active_model/serializer/adapter/json.rb +2 -0
  38. data/lib/active_model/serializer/adapter/json_api.rb +2 -0
  39. data/lib/active_model/serializer/adapter/null.rb +2 -0
  40. data/lib/active_model/serializer/adapter.rb +2 -0
  41. data/lib/active_model/serializer/array_serializer.rb +10 -5
  42. data/lib/active_model/serializer/association.rb +64 -10
  43. data/lib/active_model/serializer/attribute.rb +2 -0
  44. data/lib/active_model/serializer/belongs_to_reflection.rb +6 -3
  45. data/lib/active_model/serializer/collection_serializer.rb +39 -13
  46. data/lib/active_model/serializer/{caching.rb → concerns/caching.rb} +87 -116
  47. data/lib/active_model/serializer/error_serializer.rb +13 -7
  48. data/lib/active_model/serializer/errors_serializer.rb +27 -20
  49. data/lib/active_model/serializer/field.rb +2 -0
  50. data/lib/active_model/serializer/fieldset.rb +2 -0
  51. data/lib/active_model/serializer/has_many_reflection.rb +5 -3
  52. data/lib/active_model/serializer/has_one_reflection.rb +3 -4
  53. data/lib/active_model/serializer/lazy_association.rb +99 -0
  54. data/lib/active_model/serializer/link.rb +23 -0
  55. data/lib/active_model/serializer/lint.rb +136 -130
  56. data/lib/active_model/serializer/null.rb +2 -0
  57. data/lib/active_model/serializer/reflection.rb +132 -67
  58. data/lib/active_model/serializer/version.rb +3 -1
  59. data/lib/active_model/serializer.rb +308 -82
  60. data/lib/active_model_serializers/adapter/attributes.rb +5 -66
  61. data/lib/active_model_serializers/adapter/base.rb +41 -39
  62. data/lib/active_model_serializers/adapter/json.rb +2 -0
  63. data/lib/active_model_serializers/adapter/json_api/deserialization.rb +4 -2
  64. data/lib/active_model_serializers/adapter/json_api/error.rb +2 -0
  65. data/lib/active_model_serializers/adapter/json_api/jsonapi.rb +2 -0
  66. data/lib/active_model_serializers/adapter/json_api/link.rb +3 -1
  67. data/lib/active_model_serializers/adapter/json_api/meta.rb +2 -0
  68. data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +49 -21
  69. data/lib/active_model_serializers/adapter/json_api/relationship.rb +77 -23
  70. data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +41 -10
  71. data/lib/active_model_serializers/adapter/json_api.rb +84 -65
  72. data/lib/active_model_serializers/adapter/null.rb +2 -0
  73. data/lib/active_model_serializers/adapter.rb +9 -1
  74. data/lib/active_model_serializers/callbacks.rb +2 -0
  75. data/lib/active_model_serializers/deprecate.rb +3 -2
  76. data/lib/active_model_serializers/deserialization.rb +4 -0
  77. data/lib/active_model_serializers/json_pointer.rb +2 -0
  78. data/lib/active_model_serializers/logging.rb +2 -0
  79. data/lib/active_model_serializers/lookup_chain.rb +82 -0
  80. data/lib/active_model_serializers/model.rb +111 -28
  81. data/lib/active_model_serializers/railtie.rb +7 -1
  82. data/lib/active_model_serializers/register_jsonapi_renderer.rb +46 -31
  83. data/lib/active_model_serializers/serializable_resource.rb +10 -7
  84. data/lib/active_model_serializers/serialization_context.rb +12 -3
  85. data/lib/active_model_serializers/test/schema.rb +4 -2
  86. data/lib/active_model_serializers/test/serializer.rb +2 -0
  87. data/lib/active_model_serializers/test.rb +2 -0
  88. data/lib/active_model_serializers.rb +35 -10
  89. data/lib/generators/rails/resource_override.rb +3 -1
  90. data/lib/generators/rails/serializer_generator.rb +6 -4
  91. data/lib/grape/active_model_serializers.rb +9 -5
  92. data/lib/grape/formatters/active_model_serializers.rb +21 -2
  93. data/lib/grape/helpers/active_model_serializers.rb +3 -0
  94. data/lib/tasks/rubocop.rake +55 -0
  95. data/test/action_controller/adapter_selector_test.rb +16 -5
  96. data/test/action_controller/explicit_serializer_test.rb +7 -4
  97. data/test/action_controller/json/include_test.rb +108 -27
  98. data/test/action_controller/json_api/deserialization_test.rb +3 -1
  99. data/test/action_controller/json_api/errors_test.rb +10 -9
  100. data/test/action_controller/json_api/fields_test.rb +68 -0
  101. data/test/action_controller/json_api/linked_test.rb +31 -24
  102. data/test/action_controller/json_api/pagination_test.rb +33 -23
  103. data/test/action_controller/json_api/transform_test.rb +13 -3
  104. data/test/action_controller/lookup_proc_test.rb +51 -0
  105. data/test/action_controller/namespace_lookup_test.rb +234 -0
  106. data/test/action_controller/serialization_scope_name_test.rb +14 -6
  107. data/test/action_controller/serialization_test.rb +23 -12
  108. data/test/active_model_serializers/adapter_for_test.rb +2 -0
  109. data/test/active_model_serializers/json_pointer_test.rb +17 -13
  110. data/test/active_model_serializers/logging_test.rb +2 -0
  111. data/test/active_model_serializers/model_test.rb +139 -4
  112. data/test/active_model_serializers/railtie_test_isolated.rb +14 -7
  113. data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +163 -0
  114. data/test/active_model_serializers/serialization_context_test_isolated.rb +25 -10
  115. data/test/active_model_serializers/test/schema_test.rb +5 -2
  116. data/test/active_model_serializers/test/serializer_test.rb +2 -0
  117. data/test/active_record_test.rb +2 -0
  118. data/test/adapter/attributes_test.rb +42 -0
  119. data/test/adapter/deprecation_test.rb +2 -0
  120. data/test/adapter/json/belongs_to_test.rb +2 -0
  121. data/test/adapter/json/collection_test.rb +16 -0
  122. data/test/adapter/json/has_many_test.rb +12 -2
  123. data/test/adapter/json/transform_test.rb +17 -15
  124. data/test/adapter/json_api/belongs_to_test.rb +2 -0
  125. data/test/adapter/json_api/collection_test.rb +6 -3
  126. data/test/adapter/json_api/errors_test.rb +19 -19
  127. data/test/adapter/json_api/fields_test.rb +14 -3
  128. data/test/adapter/json_api/has_many_explicit_serializer_test.rb +2 -0
  129. data/test/adapter/json_api/has_many_test.rb +51 -20
  130. data/test/adapter/json_api/has_one_test.rb +2 -0
  131. data/test/adapter/json_api/include_data_if_sideloaded_test.rb +215 -0
  132. data/test/adapter/json_api/json_api_test.rb +7 -7
  133. data/test/adapter/json_api/linked_test.rb +35 -12
  134. data/test/adapter/json_api/links_test.rb +22 -3
  135. data/test/adapter/json_api/pagination_links_test.rb +55 -13
  136. data/test/adapter/json_api/parse_test.rb +3 -1
  137. data/test/adapter/json_api/relationship_test.rb +311 -73
  138. data/test/adapter/json_api/resource_meta_test.rb +5 -3
  139. data/test/adapter/json_api/toplevel_jsonapi_test.rb +2 -0
  140. data/test/adapter/json_api/transform_test.rb +265 -253
  141. data/test/adapter/json_api/type_test.rb +170 -36
  142. data/test/adapter/json_test.rb +10 -7
  143. data/test/adapter/null_test.rb +3 -2
  144. data/test/adapter/polymorphic_test.rb +54 -5
  145. data/test/adapter_test.rb +3 -1
  146. data/test/array_serializer_test.rb +2 -0
  147. data/test/benchmark/app.rb +3 -1
  148. data/test/benchmark/benchmarking_support.rb +3 -1
  149. data/test/benchmark/bm_active_record.rb +83 -0
  150. data/test/benchmark/bm_adapter.rb +40 -0
  151. data/test/benchmark/bm_caching.rb +18 -16
  152. data/test/benchmark/bm_lookup_chain.rb +85 -0
  153. data/test/benchmark/bm_transform.rb +23 -10
  154. data/test/benchmark/controllers.rb +18 -17
  155. data/test/benchmark/fixtures.rb +74 -72
  156. data/test/cache_test.rb +301 -69
  157. data/test/collection_serializer_test.rb +33 -14
  158. data/test/fixtures/active_record.rb +47 -10
  159. data/test/fixtures/poro.rb +128 -183
  160. data/test/generators/scaffold_controller_generator_test.rb +2 -0
  161. data/test/generators/serializer_generator_test.rb +25 -5
  162. data/test/grape_test.rb +172 -56
  163. data/test/lint_test.rb +3 -1
  164. data/test/logger_test.rb +15 -11
  165. data/test/poro_test.rb +2 -0
  166. data/test/serializable_resource_test.rb +20 -22
  167. data/test/serializers/association_macros_test.rb +5 -2
  168. data/test/serializers/associations_test.rb +274 -49
  169. data/test/serializers/attribute_test.rb +7 -3
  170. data/test/serializers/attributes_test.rb +3 -1
  171. data/test/serializers/caching_configuration_test_isolated.rb +8 -6
  172. data/test/serializers/configuration_test.rb +2 -0
  173. data/test/serializers/fieldset_test.rb +3 -1
  174. data/test/serializers/meta_test.rb +14 -6
  175. data/test/serializers/options_test.rb +19 -6
  176. data/test/serializers/read_attribute_for_serialization_test.rb +5 -3
  177. data/test/serializers/reflection_test.rb +481 -0
  178. data/test/serializers/root_test.rb +3 -1
  179. data/test/serializers/serialization_test.rb +4 -2
  180. data/test/serializers/serializer_for_test.rb +14 -10
  181. data/test/serializers/serializer_for_with_namespace_test.rb +90 -0
  182. data/test/support/isolated_unit.rb +11 -4
  183. data/test/support/rails5_shims.rb +10 -2
  184. data/test/support/rails_app.rb +4 -9
  185. data/test/support/serialization_testing.rb +33 -5
  186. data/test/test_helper.rb +15 -0
  187. metadata +126 -46
  188. data/.rubocop_todo.yml +0 -167
  189. data/docs/ARCHITECTURE.md +0 -126
  190. data/lib/active_model/serializer/associations.rb +0 -100
  191. data/lib/active_model/serializer/attributes.rb +0 -82
  192. data/lib/active_model/serializer/collection_reflection.rb +0 -7
  193. data/lib/active_model/serializer/configuration.rb +0 -35
  194. data/lib/active_model/serializer/include_tree.rb +0 -111
  195. data/lib/active_model/serializer/links.rb +0 -35
  196. data/lib/active_model/serializer/meta.rb +0 -29
  197. data/lib/active_model/serializer/singular_reflection.rb +0 -7
  198. data/lib/active_model/serializer/type.rb +0 -25
  199. data/lib/active_model_serializers/key_transform.rb +0 -70
  200. data/test/active_model_serializers/key_transform_test.rb +0 -263
  201. data/test/adapter/json_api/has_many_embed_ids_test.rb +0 -43
  202. data/test/adapter/json_api/relationships_test.rb +0 -199
  203. data/test/adapter/json_api/resource_identifier_test.rb +0 -85
  204. data/test/include_tree/from_include_args_test.rb +0 -26
  205. data/test/include_tree/from_string_test.rb +0 -94
  206. data/test/include_tree/include_args_to_hash_test.rb +0 -64
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
  require 'will_paginate/array'
3
5
  require 'kaminari'
@@ -13,11 +15,11 @@ module ActiveModelSerializers
13
15
  def setup
14
16
  ActionController::Base.cache_store.clear
15
17
  @array = [
16
- Profile.new({ id: 1, name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }),
17
- Profile.new({ id: 2, name: 'Name 2', description: 'Description 2', comments: 'Comments 2' }),
18
- Profile.new({ id: 3, name: 'Name 3', description: 'Description 3', comments: 'Comments 3' }),
19
- Profile.new({ id: 4, name: 'Name 4', description: 'Description 4', comments: 'Comments 4' }),
20
- Profile.new({ id: 5, name: 'Name 5', description: 'Description 5', comments: 'Comments 5' })
18
+ Profile.new(id: 1, name: 'Name 1', description: 'Description 1', comments: 'Comments 1'),
19
+ Profile.new(id: 2, name: 'Name 2', description: 'Description 2', comments: 'Comments 2'),
20
+ Profile.new(id: 3, name: 'Name 3', description: 'Description 3', comments: 'Comments 3'),
21
+ Profile.new(id: 4, name: 'Name 4', description: 'Description 4', comments: 'Comments 4'),
22
+ Profile.new(id: 5, name: 'Name 5', description: 'Description 5', comments: 'Comments 5')
21
23
  ]
22
24
  end
23
25
 
@@ -43,7 +45,8 @@ module ActiveModelSerializers
43
45
  end
44
46
 
45
47
  def data
46
- { data: [
48
+ {
49
+ data: [
47
50
  { id: '1', type: 'profiles', attributes: { name: 'Name 1', description: 'Description 1' } },
48
51
  { id: '2', type: 'profiles', attributes: { name: 'Name 2', description: 'Description 2' } },
49
52
  { id: '3', type: 'profiles', attributes: { name: 'Name 3', description: 'Description 3' } },
@@ -53,6 +56,16 @@ module ActiveModelSerializers
53
56
  }
54
57
  end
55
58
 
59
+ def empty_collection_links
60
+ {
61
+ self: "#{URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2",
62
+ first: "#{URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2",
63
+ prev: nil,
64
+ next: nil,
65
+ last: "#{URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2"
66
+ }
67
+ end
68
+
56
69
  def links
57
70
  {
58
71
  links: {
@@ -70,12 +83,14 @@ module ActiveModelSerializers
70
83
  links: {
71
84
  self: "#{URI}?page%5Bnumber%5D=3&page%5Bsize%5D=2",
72
85
  first: "#{URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2",
73
- prev: "#{URI}?page%5Bnumber%5D=2&page%5Bsize%5D=2"
86
+ prev: "#{URI}?page%5Bnumber%5D=2&page%5Bsize%5D=2",
87
+ next: nil,
88
+ last: "#{URI}?page%5Bnumber%5D=3&page%5Bsize%5D=2"
74
89
  }
75
90
  }
76
91
  end
77
92
 
78
- def expected_response_without_pagination_links
93
+ def expected_response_when_unpaginatable
79
94
  data
80
95
  end
81
96
 
@@ -86,6 +101,12 @@ module ActiveModelSerializers
86
101
  end
87
102
  end
88
103
 
104
+ def expected_response_without_pagination_links
105
+ {}.tap do |hash|
106
+ hash[:data] = data.values.flatten[2..3]
107
+ end
108
+ end
109
+
89
110
  def expected_response_with_pagination_links_and_additional_params
90
111
  new_links = links[:links].each_with_object({}) { |(key, value), hash| hash[key] = "#{value}&test=test" }
91
112
  {}.tap do |hash|
@@ -101,10 +122,10 @@ module ActiveModelSerializers
101
122
  end
102
123
  end
103
124
 
104
- def expected_response_with_no_data_pagination_links
125
+ def expected_response_with_empty_collection_pagination_links
105
126
  {}.tap do |hash|
106
127
  hash[:data] = []
107
- hash[:links] = {}
128
+ hash.merge! links: empty_collection_links
108
129
  end
109
130
  end
110
131
 
@@ -121,7 +142,7 @@ module ActiveModelSerializers
121
142
  end
122
143
 
123
144
  def test_pagination_links_with_additional_params
124
- adapter = load_adapter(using_will_paginate, mock_request({ test: 'test' }))
145
+ adapter = load_adapter(using_will_paginate, mock_request(test: 'test'))
125
146
 
126
147
  assert_equal expected_response_with_pagination_links_and_additional_params,
127
148
  adapter.serializable_hash
@@ -132,7 +153,7 @@ module ActiveModelSerializers
132
153
 
133
154
  adapter = load_adapter(using_kaminari(1), mock_request)
134
155
 
135
- assert_equal expected_response_with_no_data_pagination_links, adapter.serializable_hash
156
+ assert_equal expected_response_with_empty_collection_pagination_links, adapter.serializable_hash
136
157
  end
137
158
 
138
159
  def test_pagination_links_when_zero_results_will_paginate
@@ -140,7 +161,7 @@ module ActiveModelSerializers
140
161
 
141
162
  adapter = load_adapter(using_will_paginate(1), mock_request)
142
163
 
143
- assert_equal expected_response_with_no_data_pagination_links, adapter.serializable_hash
164
+ assert_equal expected_response_with_empty_collection_pagination_links, adapter.serializable_hash
144
165
  end
145
166
 
146
167
  def test_last_page_pagination_links_using_kaminari
@@ -158,7 +179,28 @@ module ActiveModelSerializers
158
179
  def test_not_showing_pagination_links
159
180
  adapter = load_adapter(@array, mock_request)
160
181
 
182
+ assert_equal expected_response_when_unpaginatable, adapter.serializable_hash
183
+ end
184
+
185
+ def test_raises_descriptive_error_when_serialization_context_unset
186
+ render_options = { adapter: :json_api }
187
+ adapter = serializable(using_kaminari, render_options)
188
+ exception_class = ActiveModelSerializers::Adapter::JsonApi::PaginationLinks::MissingSerializationContextError
189
+
190
+ exception = assert_raises(exception_class) do
191
+ adapter.as_json
192
+ end
193
+ assert_equal exception_class, exception.class
194
+ assert_match(/CollectionSerializer#paginated\?/, exception.message)
195
+ end
196
+
197
+ def test_pagination_links_not_present_when_disabled
198
+ ActiveModel::Serializer.config.jsonapi_pagination_links_enabled = false
199
+ adapter = load_adapter(using_kaminari, mock_request)
200
+
161
201
  assert_equal expected_response_without_pagination_links, adapter.serializable_hash
202
+ ensure
203
+ ActiveModel::Serializer.config.jsonapi_pagination_links_enabled = true
162
204
  end
163
205
  end
164
206
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
  module ActiveModelSerializers
3
5
  module Adapter
@@ -125,7 +127,7 @@ module ActiveModelSerializers
125
127
  src: 'http://example.com/images/productivity.png',
126
128
  author_id: nil,
127
129
  photographer_id: '9',
128
- photographer_type: 'people',
130
+ photographer_type: 'Person',
129
131
  comment_ids: %w(1 2)
130
132
  }
131
133
  assert_equal(expected, parsed_hash)
@@ -1,16 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  module ActiveModelSerializers
4
6
  module Adapter
5
7
  class JsonApi
6
8
  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
9
  def test_relationship_with_data
15
10
  expected = {
16
11
  data: {
@@ -18,26 +13,29 @@ module ActiveModelSerializers
18
13
  type: 'blogs'
19
14
  }
20
15
  }
21
- test_relationship(expected, options: { include_data: true })
16
+
17
+ model_attributes = { blog: Blog.new(id: 1) }
18
+ relationship_name = :blog
19
+ model = new_model(model_attributes)
20
+ actual = build_serializer_and_serialize_relationship(model, relationship_name) do
21
+ has_one :blog
22
+ end
23
+ assert_equal(expected, actual)
22
24
  end
23
25
 
24
26
  def test_relationship_with_nil_model
25
- @serializer = BlogSerializer.new(nil)
26
27
  expected = { data: nil }
27
- test_relationship(expected, options: { include_data: true })
28
- end
29
28
 
30
- def test_relationship_with_nil_serializer
31
- @serializer = nil
32
- expected = { data: nil }
33
- test_relationship(expected, options: { include_data: true })
29
+ model_attributes = { blog: nil }
30
+ relationship_name = :blog
31
+ model = new_model(model_attributes)
32
+ actual = build_serializer_and_serialize_relationship(model, relationship_name) do
33
+ has_one :blog
34
+ end
35
+ assert_equal(expected, actual)
34
36
  end
35
37
 
36
38
  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
39
  expected = {
42
40
  data: [
43
41
  {
@@ -50,110 +48,350 @@ module ActiveModelSerializers
50
48
  }
51
49
  ]
52
50
  }
53
- test_relationship(expected, options: { include_data: true })
51
+
52
+ model_attributes = { posts: [Post.new(id: 1), Post.new(id: 2)] }
53
+ relationship_name = :posts
54
+ model = new_model(model_attributes)
55
+ actual = build_serializer_and_serialize_relationship(model, relationship_name) do
56
+ has_many :posts
57
+ end
58
+ assert_equal(expected, actual)
54
59
  end
55
60
 
56
61
  def test_relationship_data_not_included
57
- test_relationship({}, options: { include_data: false })
58
- end
62
+ expected = { meta: {} }
59
63
 
60
- def test_relationship_simple_link
61
- links = { self: 'a link' }
62
- test_relationship({ links: { self: 'a link' } }, links: links)
64
+ model_attributes = { blog: :does_not_matter }
65
+ relationship_name = :blog
66
+ model = new_model(model_attributes)
67
+ actual = build_serializer_and_serialize_relationship(model, relationship_name) do
68
+ has_one :blog do
69
+ include_data false
70
+ end
71
+ end
72
+ assert_equal(expected, actual)
63
73
  end
64
74
 
65
75
  def test_relationship_many_links
66
- links = {
67
- self: 'a link',
68
- related: 'another link'
69
- }
70
76
  expected = {
71
77
  links: {
72
78
  self: 'a link',
73
79
  related: 'another link'
74
80
  }
75
81
  }
76
- test_relationship(expected, links: links)
77
- end
78
82
 
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
+ model_attributes = { blog: :does_not_matter }
84
+ relationship_name = :blog
85
+ model = new_model(model_attributes)
86
+ actual = build_serializer_and_serialize_relationship(model, relationship_name) do
87
+ has_one :blog do
88
+ include_data false
89
+ link :self, 'a link'
90
+ link :related, 'another link'
91
+ end
92
+ end
93
+ assert_equal(expected, actual)
83
94
  end
84
95
 
85
96
  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
97
  expected = {
93
98
  links: {
94
99
  self: {
95
- href: @blog.id.to_s,
96
- meta: { id: @blog.id }
100
+ href: '1',
101
+ meta: { id: 1 }
97
102
  }
98
103
  }
99
104
  }
100
- test_relationship(expected, links: links)
105
+
106
+ model_attributes = { blog: Blog.new(id: 1) }
107
+ relationship_name = :blog
108
+ model = new_model(model_attributes)
109
+ actual = build_serializer_and_serialize_relationship(model, relationship_name) do
110
+ has_one :blog do
111
+ include_data false
112
+ link :self do
113
+ href object.blog.id.to_s
114
+ meta(id: object.blog.id)
115
+ end
116
+ end
117
+ end
118
+ assert_equal(expected, actual)
101
119
  end
102
120
 
103
121
  def test_relationship_simple_meta
104
- meta = { id: '1' }
105
- expected = { meta: meta }
106
- test_relationship(expected, meta: meta)
122
+ expected = { meta: { id: '1' } }
123
+
124
+ model_attributes = { blog: Blog.new(id: 1) }
125
+ relationship_name = :blog
126
+ model = new_model(model_attributes)
127
+ actual = build_serializer_and_serialize_relationship(model, relationship_name) do
128
+ has_one :blog do
129
+ include_data false
130
+ meta(id: object.blog.id.to_s)
131
+ end
132
+ end
133
+ assert_equal(expected, actual)
107
134
  end
108
135
 
109
136
  def test_relationship_block_meta
110
- meta = proc do
111
- { id: object.id }
112
- end
113
137
  expected = {
114
138
  meta: {
115
- id: @blog.id
139
+ id: 1
116
140
  }
117
141
  }
118
- test_relationship(expected, meta: meta)
142
+
143
+ model_attributes = { blog: Blog.new(id: 1) }
144
+ relationship_name = :blog
145
+ model = new_model(model_attributes)
146
+ actual = build_serializer_and_serialize_relationship(model, relationship_name) do
147
+ has_one :blog do
148
+ include_data false
149
+ meta(id: object.blog.id)
150
+ end
151
+ end
152
+ assert_equal(expected, actual)
119
153
  end
120
154
 
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
155
+ def test_relationship_simple_link
156
+ expected = {
157
+ data: {
158
+ id: '1337',
159
+ type: 'bios'
160
+ },
161
+ links: {
162
+ self: '//example.com/link_author/relationships/bio'
163
+ }
164
+ }
165
+
166
+ model_attributes = { bio: Bio.new(id: 1337) }
167
+ relationship_name = :bio
168
+ model = new_model(model_attributes)
169
+ actual = build_serializer_and_serialize_relationship(model, relationship_name) do
170
+ has_one :bio do
171
+ link :self, '//example.com/link_author/relationships/bio'
127
172
  end
173
+ end
174
+ assert_equal(expected, actual)
175
+ end
128
176
 
177
+ def test_relationship_block_link
178
+ expected = {
179
+ data: { id: '1337', type: 'profiles' },
180
+ links: { related: '//example.com/profiles/1337' }
129
181
  }
130
- meta = proc do
131
- { id: object.id }
182
+
183
+ model_attributes = { profile: Profile.new(id: 1337) }
184
+ relationship_name = :profile
185
+ model = new_model(model_attributes)
186
+ actual = build_serializer_and_serialize_relationship(model, relationship_name) do
187
+ has_one :profile do
188
+ id = object.profile.id
189
+ link :related do
190
+ "//example.com/profiles/#{id}" if id != 123
191
+ end
192
+ end
132
193
  end
194
+ assert_equal(expected, actual)
195
+ end
196
+
197
+ def test_relationship_with_everything
133
198
  expected = {
134
- data: {
135
- id: '1',
136
- type: 'blogs'
137
- },
199
+ data: [{ id: '1337', type: 'likes' }],
138
200
  links: {
139
- self: 'a link',
140
201
  related: {
141
- href: '1', meta: 1
202
+ href: '//example.com/likes/1337',
203
+ meta: { ids: '1337' }
142
204
  }
143
205
  },
144
- meta: {
145
- id: @blog.id
206
+ meta: { liked: true }
207
+ }
208
+
209
+ model_attributes = { likes: [Like.new(id: 1337)] }
210
+ relationship_name = :likes
211
+ model = new_model(model_attributes)
212
+ actual = build_serializer_and_serialize_relationship(model, relationship_name) do
213
+ has_many :likes do
214
+ link :related do
215
+ ids = object.likes.map(&:id).join(',')
216
+ href "//example.com/likes/#{ids}"
217
+ meta ids: ids
218
+ end
219
+ meta liked: object.likes.any?
220
+ end
221
+ end
222
+ assert_equal(expected, actual)
223
+ end
224
+
225
+ def test_relationship_nil_link
226
+ expected = {
227
+ data: { id: '123', type: 'profiles' }
228
+ }
229
+
230
+ model_attributes = { profile: Profile.new(id: 123) }
231
+ relationship_name = :profile
232
+ model = new_model(model_attributes)
233
+ actual = build_serializer_and_serialize_relationship(model, relationship_name) do
234
+ has_one :profile do
235
+ id = object.profile.id
236
+ link :related do
237
+ "//example.com/profiles/#{id}" if id != 123
238
+ end
239
+ end
240
+ end
241
+ assert_equal(expected, actual)
242
+ end
243
+
244
+ def test_relationship_block_link_href
245
+ expected = {
246
+ data: [{ id: '1337', type: 'locations' }],
247
+ links: {
248
+ related: { href: '//example.com/locations/1337' }
146
249
  }
147
250
  }
148
- test_relationship(expected, meta: meta, options: { include_data: true }, links: links)
251
+
252
+ model_attributes = { locations: [Location.new(id: 1337)] }
253
+ relationship_name = :locations
254
+ model = new_model(model_attributes)
255
+ actual = build_serializer_and_serialize_relationship(model, relationship_name) do
256
+ has_many :locations do
257
+ link :related do
258
+ ids = object.locations.map(&:id).join(',')
259
+ href "//example.com/locations/#{ids}"
260
+ end
261
+ end
262
+ end
263
+ assert_equal(expected, actual)
264
+ end
265
+
266
+ def test_relationship_block_link_href_and_meta
267
+ expected = {
268
+ data: [{ id: '1337', type: 'posts' }],
269
+ links: {
270
+ related: {
271
+ href: '//example.com/posts/1337',
272
+ meta: { ids: '1337' }
273
+ }
274
+ }
275
+ }
276
+
277
+ model_attributes = { posts: [Post.new(id: 1337, comments: [], author: nil)] }
278
+ relationship_name = :posts
279
+ model = new_model(model_attributes)
280
+ actual = build_serializer_and_serialize_relationship(model, relationship_name) do
281
+ has_many :posts do
282
+ link :related do
283
+ ids = object.posts.map(&:id).join(',')
284
+ href "//example.com/posts/#{ids}"
285
+ meta ids: ids
286
+ end
287
+ end
288
+ end
289
+ assert_equal(expected, actual)
290
+ end
291
+
292
+ def test_relationship_block_link_meta
293
+ expected = {
294
+ data: [{ id: '1337', type: 'comments' }],
295
+ links: {
296
+ self: {
297
+ meta: { ids: [1] }
298
+ }
299
+ }
300
+ }
301
+
302
+ model_attributes = { comments: [Comment.new(id: 1337)] }
303
+ relationship_name = :comments
304
+ model = new_model(model_attributes)
305
+ actual = build_serializer_and_serialize_relationship(model, relationship_name) do
306
+ has_many :comments do
307
+ link :self do
308
+ meta ids: [1]
309
+ end
310
+ end
311
+ end
312
+ assert_equal(expected, actual)
313
+ end
314
+
315
+ def test_relationship_meta
316
+ expected = {
317
+ data: [{ id: 'from-serializer-method', type: 'roles' }],
318
+ meta: { count: 1 }
319
+ }
320
+
321
+ model_attributes = { roles: [Role.new(id: 'from-record')] }
322
+ relationship_name = :roles
323
+ model = new_model(model_attributes)
324
+ actual = build_serializer_and_serialize_relationship(model, relationship_name) do
325
+ has_many :roles do |serializer|
326
+ meta count: object.roles.count
327
+ serializer.cached_roles
328
+ end
329
+ def cached_roles
330
+ [
331
+ Role.new(id: 'from-serializer-method')
332
+ ]
333
+ end
334
+ end
335
+ assert_equal(expected, actual)
336
+ end
337
+
338
+ def test_relationship_not_including_data
339
+ expected = {
340
+ links: { self: '//example.com/link_author/relationships/blog' }
341
+ }
342
+
343
+ model_attributes = { blog: Object }
344
+ relationship_name = :blog
345
+ model = new_model(model_attributes)
346
+ model.define_singleton_method(:read_attribute_for_serialization) do |attr|
347
+ fail 'should not be called' if attr == :blog
348
+ super(attr)
349
+ end
350
+ assert_nothing_raised do
351
+ actual = build_serializer_and_serialize_relationship(model, relationship_name) do
352
+ has_one :blog do
353
+ link :self, '//example.com/link_author/relationships/blog'
354
+ include_data false
355
+ end
356
+ end
357
+ assert_equal(expected, actual)
358
+ end
359
+ end
360
+
361
+ def test_relationship_including_data_explicit
362
+ expected = {
363
+ data: { id: '1337', type: 'authors' },
364
+ meta: { name: 'Dan Brown' }
365
+ }
366
+
367
+ model_attributes = { reviewer: Author.new(id: 1337) }
368
+ relationship_name = :reviewer
369
+ model = new_model(model_attributes)
370
+ actual = build_serializer_and_serialize_relationship(model, relationship_name) do
371
+ belongs_to :reviewer do
372
+ meta name: 'Dan Brown'
373
+ include_data true
374
+ end
375
+ end
376
+ assert_equal(expected, actual)
149
377
  end
150
378
 
151
379
  private
152
380
 
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)
381
+ def build_serializer_and_serialize_relationship(model, relationship_name, &block)
382
+ serializer_class = Class.new(ActiveModel::Serializer, &block)
383
+ hash = serializable(model, serializer: serializer_class, adapter: :json_api).serializable_hash
384
+ hash[:data][:relationships][relationship_name]
385
+ end
386
+
387
+ def new_model(model_attributes)
388
+ Class.new(ActiveModelSerializers::Model) do
389
+ attributes(*model_attributes.keys)
390
+
391
+ def self.name
392
+ 'TestModel'
393
+ end
394
+ end.new(model_attributes)
157
395
  end
158
396
  end
159
397
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  module ActiveModel
@@ -68,9 +70,9 @@ module ActiveModel
68
70
  adapter: :json_api
69
71
  ).serializable_hash
70
72
  expected = {
71
- :data => [
72
- { :id => '1337', :type => 'posts', :meta => { :"comments-count" => 0 } },
73
- { :id => '1339', :type => 'posts', :meta => { :"comments-count" => 1 } }
73
+ data: [
74
+ { id: '1337', type: 'posts', meta: { :"comments-count" => 0 } },
75
+ { id: '1339', type: 'posts', meta: { :"comments-count" => 1 } }
74
76
  ]
75
77
  }
76
78
  assert_equal(expected, hash)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  module ActiveModelSerializers