active_model_serializers 0.10.0 → 0.10.7

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 (171) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +6 -5
  3. data/.travis.yml +30 -21
  4. data/CHANGELOG.md +172 -2
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +23 -4
  7. data/README.md +166 -28
  8. data/Rakefile +3 -32
  9. data/active_model_serializers.gemspec +22 -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 +125 -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 +13 -3
  34. data/lib/active_model/serializer/adapter/base.rb +2 -0
  35. data/lib/active_model/serializer/array_serializer.rb +8 -5
  36. data/lib/active_model/serializer/association.rb +62 -10
  37. data/lib/active_model/serializer/belongs_to_reflection.rb +4 -3
  38. data/lib/active_model/serializer/collection_serializer.rb +39 -13
  39. data/lib/active_model/serializer/{caching.rb → concerns/caching.rb} +82 -115
  40. data/lib/active_model/serializer/error_serializer.rb +11 -7
  41. data/lib/active_model/serializer/errors_serializer.rb +25 -20
  42. data/lib/active_model/serializer/has_many_reflection.rb +3 -3
  43. data/lib/active_model/serializer/has_one_reflection.rb +1 -4
  44. data/lib/active_model/serializer/lazy_association.rb +95 -0
  45. data/lib/active_model/serializer/lint.rb +134 -130
  46. data/lib/active_model/serializer/reflection.rb +127 -67
  47. data/lib/active_model/serializer/version.rb +1 -1
  48. data/lib/active_model/serializer.rb +297 -79
  49. data/lib/active_model_serializers/adapter/attributes.rb +3 -66
  50. data/lib/active_model_serializers/adapter/base.rb +39 -39
  51. data/lib/active_model_serializers/adapter/json_api/deserialization.rb +2 -2
  52. data/lib/active_model_serializers/adapter/json_api/link.rb +1 -1
  53. data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +47 -21
  54. data/lib/active_model_serializers/adapter/json_api/relationship.rb +75 -23
  55. data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +39 -10
  56. data/lib/active_model_serializers/adapter/json_api.rb +71 -57
  57. data/lib/active_model_serializers/adapter.rb +6 -0
  58. data/lib/active_model_serializers/deprecate.rb +1 -2
  59. data/lib/active_model_serializers/deserialization.rb +2 -0
  60. data/lib/active_model_serializers/lookup_chain.rb +80 -0
  61. data/lib/active_model_serializers/model.rb +109 -28
  62. data/lib/active_model_serializers/railtie.rb +3 -1
  63. data/lib/active_model_serializers/register_jsonapi_renderer.rb +44 -31
  64. data/lib/active_model_serializers/serializable_resource.rb +6 -5
  65. data/lib/active_model_serializers/serialization_context.rb +10 -3
  66. data/lib/active_model_serializers/test/schema.rb +2 -2
  67. data/lib/active_model_serializers.rb +16 -1
  68. data/lib/generators/rails/resource_override.rb +1 -1
  69. data/lib/generators/rails/serializer_generator.rb +4 -4
  70. data/lib/grape/active_model_serializers.rb +7 -5
  71. data/lib/grape/formatters/active_model_serializers.rb +19 -2
  72. data/lib/grape/helpers/active_model_serializers.rb +1 -0
  73. data/lib/tasks/rubocop.rake +53 -0
  74. data/test/action_controller/adapter_selector_test.rb +14 -5
  75. data/test/action_controller/explicit_serializer_test.rb +5 -4
  76. data/test/action_controller/json/include_test.rb +106 -27
  77. data/test/action_controller/json_api/deserialization_test.rb +1 -1
  78. data/test/action_controller/json_api/errors_test.rb +8 -9
  79. data/test/action_controller/json_api/fields_test.rb +66 -0
  80. data/test/action_controller/json_api/linked_test.rb +29 -24
  81. data/test/action_controller/json_api/pagination_test.rb +31 -23
  82. data/test/action_controller/json_api/transform_test.rb +11 -3
  83. data/test/action_controller/lookup_proc_test.rb +49 -0
  84. data/test/action_controller/namespace_lookup_test.rb +232 -0
  85. data/test/action_controller/serialization_scope_name_test.rb +12 -6
  86. data/test/action_controller/serialization_test.rb +12 -9
  87. data/test/active_model_serializers/json_pointer_test.rb +15 -13
  88. data/test/active_model_serializers/model_test.rb +137 -4
  89. data/test/active_model_serializers/railtie_test_isolated.rb +12 -7
  90. data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +161 -0
  91. data/test/active_model_serializers/serialization_context_test_isolated.rb +23 -10
  92. data/test/active_model_serializers/test/schema_test.rb +3 -2
  93. data/test/adapter/attributes_test.rb +40 -0
  94. data/test/adapter/json/collection_test.rb +14 -0
  95. data/test/adapter/json/has_many_test.rb +10 -2
  96. data/test/adapter/json/transform_test.rb +15 -15
  97. data/test/adapter/json_api/collection_test.rb +4 -3
  98. data/test/adapter/json_api/errors_test.rb +17 -19
  99. data/test/adapter/json_api/fields_test.rb +12 -3
  100. data/test/adapter/json_api/has_many_test.rb +49 -20
  101. data/test/adapter/json_api/include_data_if_sideloaded_test.rb +213 -0
  102. data/test/adapter/json_api/json_api_test.rb +5 -7
  103. data/test/adapter/json_api/linked_test.rb +33 -12
  104. data/test/adapter/json_api/links_test.rb +4 -2
  105. data/test/adapter/json_api/pagination_links_test.rb +53 -13
  106. data/test/adapter/json_api/parse_test.rb +1 -1
  107. data/test/adapter/json_api/relationship_test.rb +309 -73
  108. data/test/adapter/json_api/resource_meta_test.rb +3 -3
  109. data/test/adapter/json_api/transform_test.rb +263 -253
  110. data/test/adapter/json_api/type_test.rb +168 -36
  111. data/test/adapter/json_test.rb +8 -7
  112. data/test/adapter/null_test.rb +1 -2
  113. data/test/adapter/polymorphic_test.rb +52 -5
  114. data/test/adapter_test.rb +1 -1
  115. data/test/benchmark/app.rb +1 -1
  116. data/test/benchmark/benchmarking_support.rb +1 -1
  117. data/test/benchmark/bm_active_record.rb +81 -0
  118. data/test/benchmark/bm_adapter.rb +38 -0
  119. data/test/benchmark/bm_caching.rb +16 -16
  120. data/test/benchmark/bm_lookup_chain.rb +83 -0
  121. data/test/benchmark/bm_transform.rb +21 -10
  122. data/test/benchmark/controllers.rb +16 -17
  123. data/test/benchmark/fixtures.rb +72 -72
  124. data/test/cache_test.rb +235 -69
  125. data/test/collection_serializer_test.rb +31 -14
  126. data/test/fixtures/active_record.rb +45 -10
  127. data/test/fixtures/poro.rb +124 -181
  128. data/test/generators/serializer_generator_test.rb +23 -5
  129. data/test/grape_test.rb +170 -56
  130. data/test/lint_test.rb +1 -1
  131. data/test/logger_test.rb +13 -11
  132. data/test/serializable_resource_test.rb +18 -22
  133. data/test/serializers/association_macros_test.rb +3 -2
  134. data/test/serializers/associations_test.rb +222 -49
  135. data/test/serializers/attribute_test.rb +5 -3
  136. data/test/serializers/attributes_test.rb +1 -1
  137. data/test/serializers/caching_configuration_test_isolated.rb +6 -6
  138. data/test/serializers/fieldset_test.rb +1 -1
  139. data/test/serializers/meta_test.rb +12 -6
  140. data/test/serializers/options_test.rb +17 -6
  141. data/test/serializers/read_attribute_for_serialization_test.rb +3 -3
  142. data/test/serializers/reflection_test.rb +427 -0
  143. data/test/serializers/root_test.rb +1 -1
  144. data/test/serializers/serialization_test.rb +2 -2
  145. data/test/serializers/serializer_for_test.rb +12 -10
  146. data/test/serializers/serializer_for_with_namespace_test.rb +88 -0
  147. data/test/support/isolated_unit.rb +9 -4
  148. data/test/support/rails5_shims.rb +8 -2
  149. data/test/support/rails_app.rb +2 -9
  150. data/test/support/serialization_testing.rb +31 -5
  151. data/test/test_helper.rb +13 -0
  152. metadata +130 -71
  153. data/.rubocop_todo.yml +0 -167
  154. data/docs/ARCHITECTURE.md +0 -126
  155. data/lib/active_model/serializer/associations.rb +0 -100
  156. data/lib/active_model/serializer/attributes.rb +0 -82
  157. data/lib/active_model/serializer/collection_reflection.rb +0 -7
  158. data/lib/active_model/serializer/configuration.rb +0 -35
  159. data/lib/active_model/serializer/include_tree.rb +0 -111
  160. data/lib/active_model/serializer/links.rb +0 -35
  161. data/lib/active_model/serializer/meta.rb +0 -29
  162. data/lib/active_model/serializer/singular_reflection.rb +0 -7
  163. data/lib/active_model/serializer/type.rb +0 -25
  164. data/lib/active_model_serializers/key_transform.rb +0 -70
  165. data/test/active_model_serializers/key_transform_test.rb +0 -263
  166. data/test/adapter/json_api/has_many_embed_ids_test.rb +0 -43
  167. data/test/adapter/json_api/relationships_test.rb +0 -199
  168. data/test/adapter/json_api/resource_identifier_test.rb +0 -85
  169. data/test/include_tree/from_include_args_test.rb +0 -26
  170. data/test/include_tree/from_string_test.rb +0 -94
  171. data/test/include_tree/include_args_to_hash_test.rb +0 -64
@@ -17,25 +17,75 @@ To solve this, in Ember, both the adapter and the serializer will need some modi
17
17
 
18
18
  ### Server-Side Changes
19
19
 
20
- there are multiple mimetypes for json that should all be parsed similarly, so
21
- in `config/initializers/mime_types.rb`:
20
+ First, set the adapter type in an initializer file:
21
+
22
+ ```ruby
23
+ # config/initializers/active_model_serializers.rb
24
+ ActiveModelSerializers.config.adapter = :json_api
25
+ ```
26
+
27
+ or:
28
+
29
+ ```ruby
30
+ # config/initializers/active_model_serializers.rb
31
+ ActiveModelSerializers.config.adapter = ActiveModelSerializers::Adapter::JsonApi
32
+ ```
33
+
34
+ You will also want to set the `key_transform` to `:unaltered` since you will adjust the attributes in your Ember serializer to use underscores instead of dashes later. You could also use `:underscore`, but `:unaltered` is better for performance.
35
+
36
+ ```ruby
37
+ # config/initializers/active_model_serializers.rb
38
+ ActiveModelSerializers.config.key_transform = :unaltered
39
+ ```
40
+
41
+ In order to properly handle JSON API responses, we need to register a JSON API renderer, like so:
42
+
43
+ ```ruby
44
+ # config/initializers/active_model_serializers.rb
45
+ ActiveSupport.on_load(:action_controller) do
46
+ require 'active_model_serializers/register_jsonapi_renderer'
47
+ end
48
+ ```
49
+ Rails also requires your controller to tell it that you accept and generate JSONAPI data. To do that, you use `respond_to` in your controller handlers to tell rails you are consuming and returning jsonapi format data. Without this, Rails will refuse to parse the request body into params. You can add `ActionController::MimeResponds` to your application controller to enable this:
50
+
51
+ ```ruby
52
+ class ApplicationController < ActionController::API
53
+ include ActionController::MimeResponds
54
+ end
55
+ ```
56
+ Then, in your controller you can tell rails you're accepting and rendering the jsonapi format:
22
57
  ```ruby
23
- api_mime_types = %W(
24
- application/vnd.api+json
25
- text/x-json
26
- application/json
27
- )
28
-
29
- Mime::Type.unregister :json
30
- Mime::Type.register 'application/json', :json, api_mime_types
58
+ # POST /post
59
+ def create
60
+ @post = Post.new(post_params)
61
+ respond_to do |format|
62
+ if @post.save
63
+ format.jsonapi { render jsonapi: @post, status: :created, location: @post }
64
+ else
65
+ format.jsonapi { render jsonapi: @post.errors, status: :unprocessable_entity }
66
+ end
67
+ end
68
+ end
69
+
70
+ # Only allow a trusted parameter "white list" through.
71
+ def post_params
72
+ ActiveModelSerializers::Deserialization.jsonapi_parse!(params, only: [:title, :body] )
73
+ end
74
+ end
31
75
  ```
32
76
 
77
+ #### Note:
78
+ In Rails 5, the "unsafe" method ( `jsonapi_parse!` vs the safe `jsonapi_parse`) throws an `InvalidDocument` exception when the payload does not meet basic criteria for JSON API deserialization.
79
+
80
+
33
81
  ### Adapter Changes
34
82
 
35
83
  ```javascript
36
84
  // app/adapters/application.js
85
+ import Ember from 'ember';
37
86
  import DS from 'ember-data';
38
87
  import ENV from "../config/environment";
88
+ const { underscore, pluralize } = Ember.String;
39
89
 
40
90
  export default DS.JSONAPIAdapter.extend({
41
91
  namespace: 'api',
@@ -46,22 +96,10 @@ export default DS.JSONAPIAdapter.extend({
46
96
 
47
97
  // allows the multiword paths in urls to be underscored
48
98
  pathForType: function(type) {
49
- let underscored = Ember.String.underscore(type);
50
- return Ember.String.pluralize(underscored);
99
+ let underscored = underscore(type);
100
+ return pluralize(underscored);
51
101
  },
52
102
 
53
- // allows queries to be sent along with a findRecord
54
- // hopefully Ember / EmberData will soon have this built in
55
- // ember-data issue tracked here:
56
- // https://github.com/emberjs/data/issues/3596
57
- urlForFindRecord(id, modelName, snapshot) {
58
- let url = this._super(...arguments);
59
- let query = Ember.get(snapshot, 'adapterOptions.query');
60
- if(query) {
61
- url += '?' + Ember.$.param(query);
62
- }
63
- return url;
64
- }
65
103
  });
66
104
  ```
67
105
 
@@ -85,22 +123,19 @@ export default DS.JSONAPISerializer.extend({
85
123
 
86
124
  ```
87
125
 
88
- ## Including Nested Resources
89
126
 
90
- Previously, `store.find` and `store.findRecord` did not allow specification of any query params.
91
- The ActiveModelSerializers default for the `include` parameter is to be `nil` meaning that if any associations are defined in your serializer, only the `id` and `type` will be in the `relationships` structure of the JSON API response.
92
- For more on `include` usage, see: [The JSON API include examples](./../general/adapters.md#JSON-API)
127
+ ## Including Nested Resources
93
128
 
94
- With the above modifications, you can execute code as below in order to include nested resources while doing a find query.
129
+ Ember Data can request related records by using `include`. Below are some examples of how to make Ember Data request the inclusion of related records. For more on `include` usage, see: [The JSON API include examples](./../general/adapters.md#JSON-API)
95
130
 
96
131
  ```javascript
97
- store.findRecord('post', postId, { adapterOptions: { query: { include: 'comments' } } });
132
+ store.findRecord('post', postId, { include: 'comments' } );
98
133
  ```
99
- will generate the path `/posts/{postId}?include='comments'`
134
+ which will generate the path /posts/{postId}?include='comments'
100
135
 
101
136
  So then in your controller, you'll want to be sure to have something like:
102
137
  ```ruby
103
- render json: @post, include: params[:include]
138
+ render jsonapi: @post, include: params[:include]
104
139
  ```
105
140
 
106
141
  If you want to use `include` on a collection, you'd write something like this:
@@ -28,7 +28,7 @@ Example supported requests
28
28
  - Relationships
29
29
  - GET /articles/1/relationships/comments
30
30
  - GET /articles/1/relationships/author
31
- - Optional: [Inclusion of related resources](http://jsonapi.org/format/#fetching-includes) `ActiveModel::Serializer::IncludeTree`
31
+ - Optional: [Inclusion of related resources](http://jsonapi.org/format/#fetching-includes) `JSONAPI::IncludeDirective`
32
32
  - GET /articles/1?`include`=comments
33
33
  - GET /articles/1?`include`=comments.author
34
34
  - GET /articles/1?`include`=author,comments.author
@@ -16,19 +16,29 @@ module ActionController
16
16
  included do
17
17
  class_attribute :_serialization_scope
18
18
  self._serialization_scope = :current_user
19
+
20
+ attr_writer :namespace_for_serializer
21
+ end
22
+
23
+ def namespace_for_serializer
24
+ @namespace_for_serializer ||= self.class.parent unless self.class.parent == Object
19
25
  end
20
26
 
21
27
  def serialization_scope
22
- send(_serialization_scope) if _serialization_scope &&
23
- respond_to?(_serialization_scope, true)
28
+ return unless _serialization_scope && respond_to?(_serialization_scope, true)
29
+
30
+ send(_serialization_scope)
24
31
  end
25
32
 
26
33
  def get_serializer(resource, options = {})
27
- if !use_adapter?
34
+ unless use_adapter?
28
35
  warn 'ActionController::Serialization#use_adapter? has been removed. '\
29
36
  "Please pass 'adapter: false' or see ActiveSupport::SerializableResource.new"
30
37
  options[:adapter] = false
31
38
  end
39
+
40
+ options.fetch(:namespace) { options[:namespace] = namespace_for_serializer }
41
+
32
42
  serializable_resource = ActiveModelSerializers::SerializableResource.new(resource, options)
33
43
  serializable_resource.serialization_scope ||= options.fetch(:scope) { serialization_scope }
34
44
  serializable_resource.serialization_scope_name = options.fetch(:scope_name) { _serialization_scope }
@@ -7,9 +7,11 @@ module ActiveModel
7
7
  deprecate :inherited, 'ActiveModelSerializers::Adapter::Base.'
8
8
  end
9
9
 
10
+ # :nocov:
10
11
  def initialize(serializer, options = {})
11
12
  super(ActiveModelSerializers::Adapter::Base.new(serializer, options))
12
13
  end
14
+ # :nocov:
13
15
  end
14
16
  end
15
17
  end
@@ -1,9 +1,12 @@
1
1
  require 'active_model/serializer/collection_serializer'
2
- class ActiveModel::Serializer
3
- class ArraySerializer < CollectionSerializer
4
- class << self
5
- extend ActiveModelSerializers::Deprecate
6
- deprecate :new, 'ActiveModel::Serializer::CollectionSerializer.'
2
+
3
+ module ActiveModel
4
+ class Serializer
5
+ class ArraySerializer < CollectionSerializer
6
+ class << self
7
+ extend ActiveModelSerializers::Deprecate
8
+ deprecate :new, 'ActiveModel::Serializer::CollectionSerializer.'
9
+ end
7
10
  end
8
11
  end
9
12
  end
@@ -1,19 +1,71 @@
1
+ require 'active_model/serializer/lazy_association'
2
+
1
3
  module ActiveModel
2
4
  class Serializer
3
- # This class hold all information about serializer's association.
5
+ # This class holds all information about serializer's association.
4
6
  #
5
- # @attr [Symbol] name
6
- # @attr [ActiveModel::Serializer] serializer
7
- # @attr [Hash{Symbol => Object}] options
8
- #
9
- # @example
10
- # Association.new(:comments, CommentSummarySerializer)
11
- #
12
- Association = Struct.new(:name, :serializer, :options, :links, :meta) do
7
+ # @api private
8
+ Association = Struct.new(:reflection, :association_options) do
9
+ attr_reader :lazy_association
10
+ delegate :object, :include_data?, :virtual_value, :collection?, to: :lazy_association
11
+
12
+ def initialize(*)
13
+ super
14
+ @lazy_association = LazyAssociation.new(reflection, association_options)
15
+ end
16
+
17
+ # @return [Symbol]
18
+ delegate :name, to: :reflection
19
+
13
20
  # @return [Symbol]
14
21
  def key
15
- options.fetch(:key, name)
22
+ reflection_options.fetch(:key, name)
23
+ end
24
+
25
+ # @return [True,False]
26
+ def key?
27
+ reflection_options.key?(:key)
28
+ end
29
+
30
+ # @return [Hash]
31
+ def links
32
+ reflection_options.fetch(:links) || {}
33
+ end
34
+
35
+ # @return [Hash, nil]
36
+ # This gets mutated, so cannot use the cached reflection_options
37
+ def meta
38
+ reflection.options[:meta]
39
+ end
40
+
41
+ def belongs_to?
42
+ reflection.foreign_key_on == :self
43
+ end
44
+
45
+ def polymorphic?
46
+ true == reflection_options[:polymorphic]
47
+ end
48
+
49
+ # @api private
50
+ def serializable_hash(adapter_options, adapter_instance)
51
+ association_serializer = lazy_association.serializer
52
+ return virtual_value if virtual_value
53
+ association_object = association_serializer && association_serializer.object
54
+ return unless association_object
55
+
56
+ serialization = association_serializer.serializable_hash(adapter_options, {}, adapter_instance)
57
+
58
+ if polymorphic? && serialization
59
+ polymorphic_type = association_object.class.name.underscore
60
+ serialization = { type: polymorphic_type, polymorphic_type.to_sym => serialization }
61
+ end
62
+
63
+ serialization
16
64
  end
65
+
66
+ private
67
+
68
+ delegate :reflection_options, to: :lazy_association
17
69
  end
18
70
  end
19
71
  end
@@ -1,9 +1,10 @@
1
1
  module ActiveModel
2
2
  class Serializer
3
3
  # @api private
4
- class BelongsToReflection < SingularReflection
5
- def macro
6
- :belongs_to
4
+ class BelongsToReflection < Reflection
5
+ # @api private
6
+ def foreign_key_on
7
+ :self
7
8
  end
8
9
  end
9
10
  end
@@ -1,7 +1,6 @@
1
1
  module ActiveModel
2
2
  class Serializer
3
3
  class CollectionSerializer
4
- NoSerializerError = Class.new(StandardError)
5
4
  include Enumerable
6
5
  delegate :each, to: :@serializers
7
6
 
@@ -11,22 +10,23 @@ module ActiveModel
11
10
  @object = resources
12
11
  @options = options
13
12
  @root = options[:root]
14
- serializer_context_class = options.fetch(:serializer_context_class, ActiveModel::Serializer)
15
- @serializers = resources.map do |resource|
16
- serializer_class = options.fetch(:serializer) { serializer_context_class.serializer_for(resource) }
17
-
18
- if serializer_class.nil? # rubocop:disable Style/GuardClause
19
- fail NoSerializerError, "No serializer found for resource: #{resource.inspect}"
20
- else
21
- serializer_class.new(resource, options.except(:serializer))
22
- end
23
- end
13
+ @serializers = serializers_from_resources
24
14
  end
25
15
 
26
16
  def success?
27
17
  true
28
18
  end
29
19
 
20
+ # @api private
21
+ def serializable_hash(adapter_options, options, adapter_instance)
22
+ include_directive = ActiveModel::Serializer.include_directive_from_options(adapter_options)
23
+ adapter_options[:cached_attributes] ||= ActiveModel::Serializer.cache_read_multi(self, adapter_instance, include_directive)
24
+ adapter_opts = adapter_options.merge(include_directive: include_directive)
25
+ serializers.map do |serializer|
26
+ serializer.serializable_hash(adapter_opts, options, adapter_instance)
27
+ end
28
+ end
29
+
30
30
  # TODO: unify naming of root, json_key, and _type. Right now, a serializer's
31
31
  # json_key comes from the root option or the object's model name, by default.
32
32
  # But, if a dev defines a custom `json_key` method with an explicit value,
@@ -46,12 +46,16 @@ module ActiveModel
46
46
  # 3. get from collection name, if a named collection
47
47
  key ||= object.respond_to?(:name) ? object.name && object.name.underscore : nil
48
48
  # 4. key may be nil for empty collection and no serializer option
49
- key && key.pluralize
49
+ key &&= key.pluralize
50
+ # 5. fail if the key cannot be determined
51
+ key || fail(ArgumentError, 'Cannot infer root key from collection type. Please
52
+ specify the root or each_serializer option, or render a JSON String')
50
53
  end
51
54
  # rubocop:enable Metrics/CyclomaticComplexity
52
55
 
53
56
  def paginated?
54
- object.respond_to?(:current_page) &&
57
+ ActiveModelSerializers.config.jsonapi_pagination_links_enabled &&
58
+ object.respond_to?(:current_page) &&
55
59
  object.respond_to?(:total_pages) &&
56
60
  object.respond_to?(:size)
57
61
  end
@@ -59,6 +63,28 @@ module ActiveModel
59
63
  protected
60
64
 
61
65
  attr_reader :serializers, :options
66
+
67
+ private
68
+
69
+ def serializers_from_resources
70
+ serializer_context_class = options.fetch(:serializer_context_class, ActiveModel::Serializer)
71
+ object.map do |resource|
72
+ serializer_from_resource(resource, serializer_context_class, options)
73
+ end
74
+ end
75
+
76
+ def serializer_from_resource(resource, serializer_context_class, options)
77
+ serializer_class = options.fetch(:serializer) do
78
+ serializer_context_class.serializer_for(resource, namespace: options[:namespace])
79
+ end
80
+
81
+ if serializer_class.nil?
82
+ ActiveModelSerializers.logger.debug "No serializer found for resource: #{resource.inspect}"
83
+ throw :no_serializer
84
+ else
85
+ serializer_class.new(resource, options.except(:serializer))
86
+ end
87
+ end
62
88
  end
63
89
  end
64
90
  end