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
 
3
5
  module ActiveModelSerializers
@@ -58,9 +60,10 @@ module ActiveModelSerializers
58
60
 
59
61
  def test_limiting_fields
60
62
  actual = ActiveModelSerializers::SerializableResource.new(
61
- [@first_post, @second_post], adapter: :json_api,
62
- fields: { posts: %w(title comments blog author) })
63
- .serializable_hash
63
+ [@first_post, @second_post],
64
+ adapter: :json_api,
65
+ fields: { posts: %w(title comments blog author) }
66
+ ).serializable_hash
64
67
  expected = [
65
68
  {
66
69
  id: '1',
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  module ActiveModelSerializers
@@ -12,8 +14,8 @@ module ActiveModelSerializers
12
14
 
13
15
  def test_active_model_with_error
14
16
  options = {
15
- serializer: ActiveModel::Serializer::ErrorSerializer,
16
- adapter: :json_api
17
+ serializer: ActiveModel::Serializer::ErrorSerializer,
18
+ adapter: :json_api
17
19
  }
18
20
 
19
21
  @resource.errors.add(:name, 'cannot be nil')
@@ -22,22 +24,21 @@ module ActiveModelSerializers
22
24
  assert_equal serializable_resource.serializer_instance.attributes, {}
23
25
  assert_equal serializable_resource.serializer_instance.object, @resource
24
26
 
25
- expected_errors_object =
26
- { :errors =>
27
- [
28
- {
29
- source: { pointer: '/data/attributes/name' },
30
- detail: 'cannot be nil'
31
- }
32
- ]
27
+ expected_errors_object = {
28
+ errors: [
29
+ {
30
+ source: { pointer: '/data/attributes/name' },
31
+ detail: 'cannot be nil'
32
+ }
33
+ ]
33
34
  }
34
35
  assert_equal serializable_resource.as_json, expected_errors_object
35
36
  end
36
37
 
37
38
  def test_active_model_with_multiple_errors
38
39
  options = {
39
- serializer: ActiveModel::Serializer::ErrorSerializer,
40
- adapter: :json_api
40
+ serializer: ActiveModel::Serializer::ErrorSerializer,
41
+ adapter: :json_api
41
42
  }
42
43
 
43
44
  @resource.errors.add(:name, 'cannot be nil')
@@ -48,13 +49,12 @@ module ActiveModelSerializers
48
49
  assert_equal serializable_resource.serializer_instance.attributes, {}
49
50
  assert_equal serializable_resource.serializer_instance.object, @resource
50
51
 
51
- expected_errors_object =
52
- { :errors =>
53
- [
54
- { :source => { :pointer => '/data/attributes/name' }, :detail => 'cannot be nil' },
55
- { :source => { :pointer => '/data/attributes/name' }, :detail => 'must be longer' },
56
- { :source => { :pointer => '/data/attributes/id' }, :detail => 'must be a uuid' }
57
- ]
52
+ expected_errors_object = {
53
+ errors: [
54
+ { source: { pointer: '/data/attributes/name' }, detail: 'cannot be nil' },
55
+ { source: { pointer: '/data/attributes/name' }, detail: 'must be longer' },
56
+ { source: { pointer: '/data/attributes/id' }, detail: 'must be a uuid' }
57
+ ]
58
58
  }
59
59
  assert_equal serializable_resource.as_json, expected_errors_object
60
60
  end
@@ -1,10 +1,23 @@
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 FieldsTest < ActiveSupport::TestCase
7
- Post = Class.new(::Model)
9
+ class Post < ::Model
10
+ attributes :title, :body
11
+ associations :author, :comments
12
+ end
13
+ class Author < ::Model
14
+ attributes :name, :birthday
15
+ end
16
+ class Comment < ::Model
17
+ attributes :body
18
+ associations :author, :post
19
+ end
20
+
8
21
  class PostSerializer < ActiveModel::Serializer
9
22
  type 'posts'
10
23
  attributes :title, :body
@@ -12,13 +25,11 @@ module ActiveModelSerializers
12
25
  has_many :comments
13
26
  end
14
27
 
15
- Author = Class.new(::Model)
16
28
  class AuthorSerializer < ActiveModel::Serializer
17
29
  type 'authors'
18
30
  attributes :name, :birthday
19
31
  end
20
32
 
21
- Comment = Class.new(::Model)
22
33
  class CommentSerializer < ActiveModel::Serializer
23
34
  type 'comments'
24
35
  attributes :body
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  module ActiveModelSerializers
@@ -1,9 +1,15 @@
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 HasManyTest < ActiveSupport::TestCase
9
+ class ModelWithoutSerializer < ::Model
10
+ attributes :id, :name
11
+ end
12
+
7
13
  def setup
8
14
  ActionController::Base.cache_store.clear
9
15
  @author = Author.new(id: 1, name: 'Steve K.')
@@ -26,7 +32,7 @@ module ActiveModelSerializers
26
32
  @blog.articles = [@post]
27
33
  @post.blog = @blog
28
34
  @post_without_comments.blog = nil
29
- @tag = Tag.new(id: 1, name: '#hash_tag')
35
+ @tag = ModelWithoutSerializer.new(id: 1, name: '#hash_tag')
30
36
  @post.tags = [@tag]
31
37
  @serializer = PostSerializer.new(@post)
32
38
  @adapter = ActiveModelSerializers::Adapter::JsonApi.new(@serializer)
@@ -40,6 +46,27 @@ module ActiveModelSerializers
40
46
  assert_equal(expected, @adapter.serializable_hash[:data][:relationships][:comments])
41
47
  end
42
48
 
49
+ test 'relationships can be whitelisted via fields' do
50
+ @adapter = ActiveModelSerializers::Adapter::JsonApi.new(@serializer, fields: { posts: [:author] })
51
+ result = @adapter.serializable_hash
52
+ expected = {
53
+ data: {
54
+ id: '1',
55
+ type: 'posts',
56
+ relationships: {
57
+ author: {
58
+ data: {
59
+ id: '1',
60
+ type: 'authors'
61
+ }
62
+ }
63
+ }
64
+ }
65
+ }
66
+
67
+ assert_equal expected, result
68
+ end
69
+
43
70
  def test_includes_linked_comments
44
71
  @adapter = ActiveModelSerializers::Adapter::JsonApi.new(@serializer, include: [:comments])
45
72
  expected = [{
@@ -108,18 +135,22 @@ module ActiveModelSerializers
108
135
  end
109
136
 
110
137
  def test_has_many_with_no_serializer
111
- serializer = PostWithTagsSerializer.new(@post)
138
+ post_serializer_class = Class.new(ActiveModel::Serializer) do
139
+ attributes :id
140
+ has_many :tags
141
+ end
142
+ serializer = post_serializer_class.new(@post)
112
143
  adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer)
113
144
 
114
145
  assert_equal({
115
- data: {
116
- id: '1',
117
- type: 'posts',
118
- relationships: {
119
- tags: { data: [@tag.as_json] }
120
- }
121
- }
122
- }, adapter.serializable_hash)
146
+ data: {
147
+ id: '1',
148
+ type: 'posts',
149
+ relationships: {
150
+ tags: { data: [@tag.as_json] }
151
+ }
152
+ }
153
+ }, adapter.serializable_hash)
123
154
  end
124
155
 
125
156
  def test_has_many_with_virtual_value
@@ -127,16 +158,16 @@ module ActiveModelSerializers
127
158
  adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer)
128
159
 
129
160
  assert_equal({
130
- data: {
131
- id: '1',
132
- type: 'virtual-values',
133
- relationships: {
134
- maker: { data: { type: 'makers', id: '1' } },
135
- reviews: { data: [{ type: 'reviews', id: '1' },
136
- { type: 'reviews', id: '2' }] }
137
- }
138
- }
139
- }, adapter.serializable_hash)
161
+ data: {
162
+ id: '1',
163
+ type: 'virtual-values',
164
+ relationships: {
165
+ maker: { data: { type: 'makers', id: '1' } },
166
+ reviews: { data: [{ type: 'reviews', id: '1' },
167
+ { type: 'reviews', id: '2' }] }
168
+ }
169
+ }
170
+ }, adapter.serializable_hash)
140
171
  end
141
172
  end
142
173
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  module ActiveModelSerializers
@@ -0,0 +1,215 @@
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 IncludeParamTest < ActiveSupport::TestCase
10
+ IncludeParamAuthor = Class.new(::Model) do
11
+ associations :tags, :posts, :roles
12
+ end
13
+
14
+ class CustomCommentLoader
15
+ def all
16
+ [{ foo: 'bar' }]
17
+ end
18
+ end
19
+ class Tag < ::Model
20
+ attributes :id, :name
21
+ end
22
+
23
+ class TagSerializer < ActiveModel::Serializer
24
+ type 'tags'
25
+ attributes :id, :name
26
+ end
27
+
28
+ class PostWithTagsSerializer < ActiveModel::Serializer
29
+ type 'posts'
30
+ attributes :id
31
+ has_many :tags
32
+ end
33
+
34
+ class IncludeParamAuthorSerializer < ActiveModel::Serializer
35
+ class_attribute :comment_loader
36
+
37
+ has_many :tags, serializer: TagSerializer do
38
+ link :self, '//example.com/link_author/relationships/tags'
39
+ include_data :if_sideloaded
40
+ end
41
+
42
+ has_many :unlinked_tags, serializer: TagSerializer do
43
+ include_data :if_sideloaded
44
+ end
45
+
46
+ has_many :posts, serializer: PostWithTagsSerializer do
47
+ include_data :if_sideloaded
48
+ end
49
+ has_many :locations do
50
+ include_data :if_sideloaded
51
+ end
52
+ has_many :comments do
53
+ include_data :if_sideloaded
54
+ IncludeParamAuthorSerializer.comment_loader.all
55
+ end
56
+ has_many :roles, key: :granted_roles do
57
+ include_data :if_sideloaded
58
+ end
59
+ end
60
+
61
+ def setup
62
+ IncludeParamAuthorSerializer.comment_loader = Class.new(CustomCommentLoader).new
63
+ @tag = Tag.new(id: 1337, name: 'mytag')
64
+ @role = Role.new(id: 1337, name: 'myrole')
65
+ @author = IncludeParamAuthor.new(
66
+ id: 1337,
67
+ tags: [@tag],
68
+ roles: [@role]
69
+ )
70
+ end
71
+
72
+ def test_relationship_not_loaded_when_not_included
73
+ expected = {
74
+ links: {
75
+ self: '//example.com/link_author/relationships/tags'
76
+ }
77
+ }
78
+
79
+ @author.define_singleton_method(:read_attribute_for_serialization) do |attr|
80
+ fail 'should not be called' if attr == :tags
81
+ super(attr)
82
+ end
83
+
84
+ assert_relationship(:tags, expected)
85
+ end
86
+
87
+ def test_relationship_included
88
+ expected = {
89
+ data: [
90
+ {
91
+ id: '1337',
92
+ type: 'tags'
93
+ }
94
+ ],
95
+ links: {
96
+ self: '//example.com/link_author/relationships/tags'
97
+ }
98
+ }
99
+
100
+ assert_relationship(:tags, expected, include: :tags)
101
+ end
102
+
103
+ def test_sideloads_included
104
+ expected = [
105
+ {
106
+ id: '1337',
107
+ type: 'tags',
108
+ attributes: { name: 'mytag' }
109
+ }
110
+ ]
111
+ hash = result(include: :tags)
112
+ assert_equal(expected, hash[:included])
113
+ end
114
+
115
+ def test_sideloads_included_when_using_key
116
+ expected = [
117
+ {
118
+ id: '1337',
119
+ type: 'roles',
120
+ attributes: {
121
+ name: 'myrole',
122
+ description: nil,
123
+ slug: 'myrole-1337'
124
+ },
125
+ relationships: {
126
+ author: { data: nil }
127
+ }
128
+ }
129
+ ]
130
+
131
+ hash = result(include: :granted_roles)
132
+ assert_equal(expected, hash[:included])
133
+ end
134
+
135
+ def test_sideloads_not_included_when_using_name_when_key_defined
136
+ hash = result(include: :roles)
137
+ assert_nil(hash[:included])
138
+ end
139
+
140
+ def test_nested_relationship
141
+ expected = {
142
+ data: [
143
+ {
144
+ id: '1337',
145
+ type: 'tags'
146
+ }
147
+ ],
148
+ links: {
149
+ self: '//example.com/link_author/relationships/tags'
150
+ }
151
+ }
152
+
153
+ expected_no_data = {
154
+ links: {
155
+ self: '//example.com/link_author/relationships/tags'
156
+ }
157
+ }
158
+
159
+ assert_relationship(:tags, expected, include: [:tags, { posts: :tags }])
160
+
161
+ @author.define_singleton_method(:read_attribute_for_serialization) do |attr|
162
+ fail 'should not be called' if attr == :tags
163
+ super(attr)
164
+ end
165
+
166
+ assert_relationship(:tags, expected_no_data, include: { posts: :tags })
167
+ end
168
+
169
+ def test_include_params_with_no_block
170
+ @author.define_singleton_method(:read_attribute_for_serialization) do |attr|
171
+ fail 'should not be called' if attr == :locations
172
+ super(attr)
173
+ end
174
+
175
+ expected = { meta: {} }
176
+
177
+ assert_relationship(:locations, expected)
178
+ end
179
+
180
+ def test_block_relationship
181
+ expected = {
182
+ data: [
183
+ { 'foo' => 'bar' }
184
+ ]
185
+ }
186
+
187
+ assert_relationship(:comments, expected, include: [:comments])
188
+ end
189
+
190
+ def test_node_not_included_when_no_link
191
+ expected = { meta: {} }
192
+ assert_relationship(:unlinked_tags, expected, key_transform: :unaltered)
193
+ end
194
+
195
+ private
196
+
197
+ def assert_relationship(relationship_name, expected, opts = {})
198
+ actual = relationship_data(relationship_name, opts)
199
+ assert_equal(expected, actual)
200
+ end
201
+
202
+ def result(opts)
203
+ opts = { adapter: :json_api }.merge(opts)
204
+ serializable(@author, opts).serializable_hash
205
+ end
206
+
207
+ def relationship_data(relationship_name, opts = {})
208
+ hash = result(opts)
209
+ hash[:data][:relationships][relationship_name]
210
+ end
211
+ end
212
+ end
213
+ end
214
+ end
215
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  module ActiveModelSerializers
@@ -22,13 +24,11 @@ module ActiveModelSerializers
22
24
  adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer)
23
25
 
24
26
  assert_equal({
25
- reviews: { data: [
26
- { type: 'comments', id: '1' },
27
- { type: 'comments', id: '2' }
28
- ] },
29
- writer: { data: { type: 'authors', id: '1' } },
30
- site: { data: { type: 'blogs', id: '1' } }
31
- }, adapter.serializable_hash[:data][:relationships])
27
+ reviews: { data: [{ type: 'comments', id: '1' },
28
+ { type: 'comments', id: '2' }] },
29
+ writer: { data: { type: 'authors', id: '1' } },
30
+ site: { data: { type: 'blogs', id: '1' } }
31
+ }, adapter.serializable_hash[:data][:relationships])
32
32
  end
33
33
  end
34
34
  end
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
- NestedPost = Class.new(Model)
5
+ class NestedPost < ::Model; associations :nested_posts end
4
6
  class NestedPostSerializer < ActiveModel::Serializer
5
7
  has_many :nested_posts
6
8
  end
7
-
8
9
  module ActiveModelSerializers
9
10
  module Adapter
10
11
  class JsonApi
@@ -17,7 +18,7 @@ module ActiveModelSerializers
17
18
  @first_post = Post.new(id: 10, title: 'Hello!!', body: 'Hello, world!!')
18
19
  @second_post = Post.new(id: 20, title: 'New Post', body: 'Body')
19
20
  @third_post = Post.new(id: 30, title: 'Yet Another Post', body: 'Body')
20
- @blog = Blog.new({ name: 'AMS Blog' })
21
+ @blog = Blog.new(name: 'AMS Blog')
21
22
  @first_comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
22
23
  @second_comment = Comment.new(id: 2, body: 'ZOMG ANOTHER COMMENT')
23
24
  @first_post.blog = @blog
@@ -224,6 +225,25 @@ module ActiveModelSerializers
224
225
  assert_equal expected, relationships
225
226
  end
226
227
 
228
+ def test_underscore_model_namespace_with_namespace_separator_for_linked_resource_type
229
+ spammy_post = Post.new(id: 123)
230
+ spammy_post.related = [Spam::UnrelatedLink.new(id: 456)]
231
+ serializer = SpammyPostSerializer.new(spammy_post)
232
+ adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer)
233
+ relationships = with_namespace_separator '--' do
234
+ adapter.serializable_hash[:data][:relationships]
235
+ end
236
+ expected = {
237
+ related: {
238
+ data: [{
239
+ type: 'spam--unrelated-links',
240
+ id: '456'
241
+ }]
242
+ }
243
+ }
244
+ assert_equal expected, relationships
245
+ end
246
+
227
247
  def test_multiple_references_to_same_resource
228
248
  serializer = ActiveModel::Serializer::CollectionSerializer.new([@first_comment, @second_comment])
229
249
  adapter = ActiveModelSerializers::Adapter::JsonApi.new(
@@ -283,8 +303,8 @@ module ActiveModelSerializers
283
303
  end
284
304
 
285
305
  class NoDuplicatesTest < ActiveSupport::TestCase
286
- Post = Class.new(::Model)
287
- Author = Class.new(::Model)
306
+ class Post < ::Model; associations :author end
307
+ class Author < ::Model; associations :posts, :roles, :bio end
288
308
 
289
309
  class PostSerializer < ActiveModel::Serializer
290
310
  type 'posts'
@@ -303,8 +323,8 @@ module ActiveModelSerializers
303
323
  @author.posts << @post1
304
324
  @author.posts << @post2
305
325
 
306
- @nestedpost1 = ::NestedPost.new(id: 1, nested_posts: [])
307
- @nestedpost2 = ::NestedPost.new(id: 2, nested_posts: [])
326
+ @nestedpost1 = NestedPost.new(id: 1, nested_posts: [])
327
+ @nestedpost2 = NestedPost.new(id: 2, nested_posts: [])
308
328
  @nestedpost1.nested_posts << @nestedpost1
309
329
  @nestedpost1.nested_posts << @nestedpost2
310
330
  @nestedpost2.nested_posts << @nestedpost1
@@ -341,9 +361,10 @@ module ActiveModelSerializers
341
361
 
342
362
  def test_no_duplicates_collection
343
363
  hash = ActiveModelSerializers::SerializableResource.new(
344
- [@post1, @post2], adapter: :json_api,
345
- include: '*.*')
346
- .serializable_hash
364
+ [@post1, @post2],
365
+ adapter: :json_api,
366
+ include: '*.*'
367
+ ).serializable_hash
347
368
  expected = [
348
369
  {
349
370
  type: 'authors', id: '1',
@@ -364,7 +385,8 @@ module ActiveModelSerializers
364
385
  hash = ActiveModelSerializers::SerializableResource.new(
365
386
  @nestedpost1,
366
387
  adapter: :json_api,
367
- include: '*').serializable_hash
388
+ include: '*'
389
+ ).serializable_hash
368
390
  expected = [
369
391
  type: 'nested-posts', id: '2',
370
392
  relationships: {
@@ -383,7 +405,8 @@ module ActiveModelSerializers
383
405
  hash = ActiveModelSerializers::SerializableResource.new(
384
406
  [@nestedpost1, @nestedpost2],
385
407
  adapter: :json_api,
386
- include: '*').serializable_hash
408
+ include: '*'
409
+ ).serializable_hash
387
410
  assert_nil(hash[:included])
388
411
  end
389
412
  end
@@ -1,10 +1,12 @@
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 LinksTest < ActiveSupport::TestCase
7
- LinkAuthor = Class.new(::Model)
9
+ class LinkAuthor < ::Model; associations :posts end
8
10
  class LinkAuthorSerializer < ActiveModel::Serializer
9
11
  link :self do
10
12
  href "http://example.com/link_author/#{object.id}"
@@ -17,6 +19,21 @@ module ActiveModelSerializers
17
19
  link :yet_another do
18
20
  "http://example.com/resource/#{object.id}"
19
21
  end
22
+ link :conditional1, if: -> { instance_truth } do
23
+ "http://example.com/conditional1/#{object.id}"
24
+ end
25
+ link :conditional2, if: :instance_falsey do
26
+ "http://example.com/conditional2/#{object.id}"
27
+ end
28
+ link(:nil) { nil }
29
+
30
+ def instance_truth
31
+ true
32
+ end
33
+
34
+ def instance_falsey
35
+ false
36
+ end
20
37
  end
21
38
 
22
39
  def setup
@@ -40,7 +57,8 @@ module ActiveModelSerializers
40
57
  stuff: 'value'
41
58
  }
42
59
  }
43
- }).serializable_hash
60
+ }
61
+ ).serializable_hash
44
62
  expected = {
45
63
  self: {
46
64
  href: 'http://example.com/posts',
@@ -83,7 +101,8 @@ module ActiveModelSerializers
83
101
  :"link-authors" => 'http://example.com/link_authors',
84
102
  resource: 'http://example.com/resource',
85
103
  posts: 'http://example.com/link_authors/1337/posts',
86
- :"yet-another" => 'http://example.com/resource/1337'
104
+ :"yet-another" => 'http://example.com/resource/1337',
105
+ conditional1: 'http://example.com/conditional1/1337'
87
106
  }
88
107
  assert_equal(expected, hash[:data][:links])
89
108
  end