agi_active_model_serializers 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 (220) hide show
  1. checksums.yaml +7 -0
  2. data/.github/ISSUE_TEMPLATE.md +29 -0
  3. data/.github/PULL_REQUEST_TEMPLATE.md +15 -0
  4. data/.gitignore +35 -0
  5. data/.rubocop.yml +102 -0
  6. data/.simplecov +110 -0
  7. data/.travis.yml +51 -0
  8. data/CHANGELOG.md +612 -0
  9. data/CODE_OF_CONDUCT.md +74 -0
  10. data/CONTRIBUTING.md +105 -0
  11. data/Gemfile +56 -0
  12. data/MIT-LICENSE +22 -0
  13. data/README.md +307 -0
  14. data/Rakefile +103 -0
  15. data/active_model_serializers.gemspec +63 -0
  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/README.md +41 -0
  21. data/docs/STYLE.md +58 -0
  22. data/docs/general/adapters.md +247 -0
  23. data/docs/general/caching.md +58 -0
  24. data/docs/general/configuration_options.md +169 -0
  25. data/docs/general/deserialization.md +100 -0
  26. data/docs/general/fields.md +31 -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 +279 -0
  32. data/docs/general/serializers.md +461 -0
  33. data/docs/how-open-source-maintained.jpg +0 -0
  34. data/docs/howto/add_pagination_links.md +138 -0
  35. data/docs/howto/add_relationship_links.md +137 -0
  36. data/docs/howto/add_root_key.md +55 -0
  37. data/docs/howto/grape_integration.md +42 -0
  38. data/docs/howto/outside_controller_use.md +65 -0
  39. data/docs/howto/passing_arbitrary_options.md +27 -0
  40. data/docs/howto/serialize_poro.md +32 -0
  41. data/docs/howto/test.md +154 -0
  42. data/docs/howto/upgrade_from_0_8_to_0_10.md +265 -0
  43. data/docs/integrations/ember-and-json-api.md +144 -0
  44. data/docs/integrations/grape.md +19 -0
  45. data/docs/jsonapi/errors.md +56 -0
  46. data/docs/jsonapi/schema.md +151 -0
  47. data/docs/jsonapi/schema/schema.json +366 -0
  48. data/docs/rfcs/0000-namespace.md +106 -0
  49. data/docs/rfcs/template.md +15 -0
  50. data/lib/action_controller/serialization.rb +66 -0
  51. data/lib/active_model/serializable_resource.rb +11 -0
  52. data/lib/active_model/serializer.rb +231 -0
  53. data/lib/active_model/serializer/adapter.rb +24 -0
  54. data/lib/active_model/serializer/adapter/attributes.rb +15 -0
  55. data/lib/active_model/serializer/adapter/base.rb +18 -0
  56. data/lib/active_model/serializer/adapter/json.rb +15 -0
  57. data/lib/active_model/serializer/adapter/json_api.rb +15 -0
  58. data/lib/active_model/serializer/adapter/null.rb +15 -0
  59. data/lib/active_model/serializer/array_serializer.rb +12 -0
  60. data/lib/active_model/serializer/association.rb +34 -0
  61. data/lib/active_model/serializer/attribute.rb +25 -0
  62. data/lib/active_model/serializer/belongs_to_reflection.rb +7 -0
  63. data/lib/active_model/serializer/collection_reflection.rb +7 -0
  64. data/lib/active_model/serializer/collection_serializer.rb +87 -0
  65. data/lib/active_model/serializer/concerns/associations.rb +102 -0
  66. data/lib/active_model/serializer/concerns/attributes.rb +82 -0
  67. data/lib/active_model/serializer/concerns/caching.rb +292 -0
  68. data/lib/active_model/serializer/concerns/configuration.rb +59 -0
  69. data/lib/active_model/serializer/concerns/links.rb +35 -0
  70. data/lib/active_model/serializer/concerns/meta.rb +29 -0
  71. data/lib/active_model/serializer/concerns/type.rb +25 -0
  72. data/lib/active_model/serializer/error_serializer.rb +14 -0
  73. data/lib/active_model/serializer/errors_serializer.rb +32 -0
  74. data/lib/active_model/serializer/field.rb +90 -0
  75. data/lib/active_model/serializer/fieldset.rb +31 -0
  76. data/lib/active_model/serializer/has_many_reflection.rb +7 -0
  77. data/lib/active_model/serializer/has_one_reflection.rb +7 -0
  78. data/lib/active_model/serializer/lint.rb +150 -0
  79. data/lib/active_model/serializer/null.rb +17 -0
  80. data/lib/active_model/serializer/reflection.rb +163 -0
  81. data/lib/active_model/serializer/singular_reflection.rb +7 -0
  82. data/lib/active_model/serializer/version.rb +5 -0
  83. data/lib/active_model_serializers.rb +53 -0
  84. data/lib/active_model_serializers/adapter.rb +98 -0
  85. data/lib/active_model_serializers/adapter/attributes.rb +13 -0
  86. data/lib/active_model_serializers/adapter/base.rb +83 -0
  87. data/lib/active_model_serializers/adapter/json.rb +21 -0
  88. data/lib/active_model_serializers/adapter/json_api.rb +517 -0
  89. data/lib/active_model_serializers/adapter/json_api/deserialization.rb +213 -0
  90. data/lib/active_model_serializers/adapter/json_api/error.rb +96 -0
  91. data/lib/active_model_serializers/adapter/json_api/jsonapi.rb +49 -0
  92. data/lib/active_model_serializers/adapter/json_api/link.rb +83 -0
  93. data/lib/active_model_serializers/adapter/json_api/meta.rb +37 -0
  94. data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +69 -0
  95. data/lib/active_model_serializers/adapter/json_api/relationship.rb +63 -0
  96. data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +51 -0
  97. data/lib/active_model_serializers/adapter/null.rb +9 -0
  98. data/lib/active_model_serializers/callbacks.rb +55 -0
  99. data/lib/active_model_serializers/deprecate.rb +54 -0
  100. data/lib/active_model_serializers/deserialization.rb +15 -0
  101. data/lib/active_model_serializers/json_pointer.rb +14 -0
  102. data/lib/active_model_serializers/logging.rb +122 -0
  103. data/lib/active_model_serializers/lookup_chain.rb +80 -0
  104. data/lib/active_model_serializers/model.rb +71 -0
  105. data/lib/active_model_serializers/railtie.rb +48 -0
  106. data/lib/active_model_serializers/register_jsonapi_renderer.rb +78 -0
  107. data/lib/active_model_serializers/serializable_resource.rb +82 -0
  108. data/lib/active_model_serializers/serialization_context.rb +39 -0
  109. data/lib/active_model_serializers/test.rb +7 -0
  110. data/lib/active_model_serializers/test/schema.rb +138 -0
  111. data/lib/active_model_serializers/test/serializer.rb +125 -0
  112. data/lib/generators/rails/USAGE +6 -0
  113. data/lib/generators/rails/resource_override.rb +10 -0
  114. data/lib/generators/rails/serializer_generator.rb +36 -0
  115. data/lib/generators/rails/templates/serializer.rb.erb +15 -0
  116. data/lib/grape/active_model_serializers.rb +16 -0
  117. data/lib/grape/formatters/active_model_serializers.rb +32 -0
  118. data/lib/grape/helpers/active_model_serializers.rb +17 -0
  119. data/test/action_controller/adapter_selector_test.rb +53 -0
  120. data/test/action_controller/explicit_serializer_test.rb +135 -0
  121. data/test/action_controller/json/include_test.rb +246 -0
  122. data/test/action_controller/json_api/deserialization_test.rb +112 -0
  123. data/test/action_controller/json_api/errors_test.rb +40 -0
  124. data/test/action_controller/json_api/fields_test.rb +66 -0
  125. data/test/action_controller/json_api/linked_test.rb +202 -0
  126. data/test/action_controller/json_api/pagination_test.rb +116 -0
  127. data/test/action_controller/json_api/transform_test.rb +189 -0
  128. data/test/action_controller/lookup_proc_test.rb +49 -0
  129. data/test/action_controller/namespace_lookup_test.rb +232 -0
  130. data/test/action_controller/serialization_scope_name_test.rb +229 -0
  131. data/test/action_controller/serialization_test.rb +472 -0
  132. data/test/active_model_serializers/adapter_for_test.rb +208 -0
  133. data/test/active_model_serializers/json_pointer_test.rb +22 -0
  134. data/test/active_model_serializers/logging_test.rb +77 -0
  135. data/test/active_model_serializers/model_test.rb +69 -0
  136. data/test/active_model_serializers/railtie_test_isolated.rb +63 -0
  137. data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +161 -0
  138. data/test/active_model_serializers/serialization_context_test_isolated.rb +71 -0
  139. data/test/active_model_serializers/test/schema_test.rb +131 -0
  140. data/test/active_model_serializers/test/serializer_test.rb +62 -0
  141. data/test/active_record_test.rb +9 -0
  142. data/test/adapter/attributes_test.rb +43 -0
  143. data/test/adapter/deprecation_test.rb +100 -0
  144. data/test/adapter/json/belongs_to_test.rb +45 -0
  145. data/test/adapter/json/collection_test.rb +104 -0
  146. data/test/adapter/json/has_many_test.rb +45 -0
  147. data/test/adapter/json/transform_test.rb +93 -0
  148. data/test/adapter/json_api/belongs_to_test.rb +155 -0
  149. data/test/adapter/json_api/collection_test.rb +96 -0
  150. data/test/adapter/json_api/errors_test.rb +76 -0
  151. data/test/adapter/json_api/fields_test.rb +96 -0
  152. data/test/adapter/json_api/has_many_embed_ids_test.rb +43 -0
  153. data/test/adapter/json_api/has_many_explicit_serializer_test.rb +96 -0
  154. data/test/adapter/json_api/has_many_test.rb +165 -0
  155. data/test/adapter/json_api/has_one_test.rb +80 -0
  156. data/test/adapter/json_api/include_data_if_sideloaded_test.rb +168 -0
  157. data/test/adapter/json_api/json_api_test.rb +33 -0
  158. data/test/adapter/json_api/linked_test.rb +413 -0
  159. data/test/adapter/json_api/links_test.rb +95 -0
  160. data/test/adapter/json_api/pagination_links_test.rb +193 -0
  161. data/test/adapter/json_api/parse_test.rb +137 -0
  162. data/test/adapter/json_api/relationship_test.rb +397 -0
  163. data/test/adapter/json_api/resource_identifier_test.rb +110 -0
  164. data/test/adapter/json_api/resource_meta_test.rb +100 -0
  165. data/test/adapter/json_api/toplevel_jsonapi_test.rb +82 -0
  166. data/test/adapter/json_api/transform_test.rb +512 -0
  167. data/test/adapter/json_api/type_test.rb +61 -0
  168. data/test/adapter/json_test.rb +46 -0
  169. data/test/adapter/null_test.rb +22 -0
  170. data/test/adapter/polymorphic_test.rb +171 -0
  171. data/test/adapter_test.rb +67 -0
  172. data/test/array_serializer_test.rb +22 -0
  173. data/test/benchmark/app.rb +65 -0
  174. data/test/benchmark/benchmarking_support.rb +67 -0
  175. data/test/benchmark/bm_active_record.rb +81 -0
  176. data/test/benchmark/bm_adapter.rb +38 -0
  177. data/test/benchmark/bm_caching.rb +119 -0
  178. data/test/benchmark/bm_lookup_chain.rb +83 -0
  179. data/test/benchmark/bm_transform.rb +45 -0
  180. data/test/benchmark/config.ru +3 -0
  181. data/test/benchmark/controllers.rb +83 -0
  182. data/test/benchmark/fixtures.rb +219 -0
  183. data/test/cache_test.rb +595 -0
  184. data/test/collection_serializer_test.rb +123 -0
  185. data/test/fixtures/active_record.rb +113 -0
  186. data/test/fixtures/poro.rb +232 -0
  187. data/test/generators/scaffold_controller_generator_test.rb +24 -0
  188. data/test/generators/serializer_generator_test.rb +74 -0
  189. data/test/grape_test.rb +178 -0
  190. data/test/lint_test.rb +49 -0
  191. data/test/logger_test.rb +20 -0
  192. data/test/poro_test.rb +9 -0
  193. data/test/serializable_resource_test.rb +79 -0
  194. data/test/serializers/association_macros_test.rb +37 -0
  195. data/test/serializers/associations_test.rb +383 -0
  196. data/test/serializers/attribute_test.rb +153 -0
  197. data/test/serializers/attributes_test.rb +52 -0
  198. data/test/serializers/caching_configuration_test_isolated.rb +170 -0
  199. data/test/serializers/configuration_test.rb +32 -0
  200. data/test/serializers/fieldset_test.rb +14 -0
  201. data/test/serializers/meta_test.rb +202 -0
  202. data/test/serializers/options_test.rb +32 -0
  203. data/test/serializers/read_attribute_for_serialization_test.rb +79 -0
  204. data/test/serializers/root_test.rb +21 -0
  205. data/test/serializers/serialization_test.rb +55 -0
  206. data/test/serializers/serializer_for_test.rb +136 -0
  207. data/test/serializers/serializer_for_with_namespace_test.rb +88 -0
  208. data/test/support/custom_schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
  209. data/test/support/isolated_unit.rb +82 -0
  210. data/test/support/rails5_shims.rb +53 -0
  211. data/test/support/rails_app.rb +36 -0
  212. data/test/support/schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
  213. data/test/support/schemas/active_model_serializers/test/schema_test/my/show.json +6 -0
  214. data/test/support/schemas/custom/show.json +7 -0
  215. data/test/support/schemas/hyper_schema.json +93 -0
  216. data/test/support/schemas/render_using_json_api.json +43 -0
  217. data/test/support/schemas/simple_json_pointers.json +10 -0
  218. data/test/support/serialization_testing.rb +71 -0
  219. data/test/test_helper.rb +58 -0
  220. metadata +602 -0
@@ -0,0 +1,106 @@
1
+ - Start Date: (2015-10-29)
2
+ - RFC PR: https://github.com/rails-api/active_model_serializers/pull/1310
3
+ - ActiveModelSerializers Issue: https://github.com/rails-api/active_model_serializers/issues/1298
4
+
5
+ # Summary
6
+
7
+ Provide a consistent API for the user of the AMS.
8
+
9
+ # Motivation
10
+
11
+ The actual public API is defined under `ActiveModelSerializers`,
12
+ `ActiveModel::Serializer` and `ActiveModel`.
13
+
14
+ At the `ActiveModel::Serializer` we have:
15
+
16
+ - `ActiveModel::Serializer.config`
17
+ - `ActiveModel::Serializer`
18
+
19
+ At the `ActiveModelSerializers` we have:
20
+
21
+ - `ActiveModelSerializers::Model`
22
+ - `ActiveModelSerializers.logger`
23
+
24
+ At `ActiveModel` we have:
25
+
26
+ - `ActiveModel::SerializableResource`
27
+
28
+ The idea here is to provide a single namespace `ActiveModelSerializers` to the user.
29
+ Following the same idea we have on other gems like
30
+ [Devise](https://github.com/plataformatec/devise/blob/e9c82472ffe7c43a448945f77e034a0e47dde0bb/lib/devise.rb),
31
+ [Refile](https://github.com/refile/refile/blob/6b24c293d044862dafbf1bfa4606672a64903aa2/lib/refile.rb) and
32
+ [Active Job](https://github.com/rails/rails/blob/30bacc26f8f258b39e12f63fe52389a968d9c1ea/activejob/lib/active_job.rb)
33
+ for example.
34
+
35
+ This way we are clarifing the boundaries of
36
+ [ActiveModelSerializers and Rails](https://github.com/rails-api/active_model_serializers/blob/master/CHANGELOG.md#prehistory)
37
+ and make clear that the `ActiveModel::Serializer` class is no longer the primary
38
+ behavior of the ActiveModelSerializers.
39
+
40
+ # Detailed design
41
+
42
+ ## New classes and modules organization
43
+
44
+ Since this will be a big change we can do this on baby steps, read small pull requests. A
45
+ possible approach is:
46
+
47
+ - All new code will be in `lib/active_model_serializers/` using
48
+ the module namespace `ActiveModelSerializers`.
49
+ - Move all content under `ActiveModel::Serializer` to be under
50
+ `ActiveModelSerializers`, the adapter is on this steps;
51
+ - Move all content under `ActiveModel` to be under `ActiveModelSerializers`,
52
+ the `SerializableResource` is on this step;
53
+ - Change all public API that doesn't make sense, keeping in mind only to keep
54
+ this in the same namespace
55
+ - Update the README;
56
+ - Update the docs;
57
+
58
+ The following table represents the current and the desired classes and modules
59
+ at the first moment.
60
+
61
+ | Current | Desired | Notes |
62
+ |--------------------------------------------------------|--------------------------------------------------|--------------------|
63
+ | `ActiveModelSerializers` and `ActiveModel::Serializer` | `ActiveModelSerializers` | The main namespace |
64
+ | `ActiveModelSerializers.logger` | `ActiveModelSerializers.logger` ||
65
+ | `ActiveModelSerializers::Model` | `ActiveModelSerializers::Model` ||
66
+ | `ActiveModel::SerializableResource` | `ActiveModelSerializers::SerializableResource` ||
67
+ | `ActiveModel::Serializer` | `ActiveModelSerializers::Serializer` | The name can be discussed in a future pull request. For example, we can rename this to `Resource` [following this idea](https://github.com/rails-api/active_model_serializers/pull/1301/files#r42963185) more info about naming in the next section|
68
+ | `ActiveModel::Serializer.config` | `ActiveModelSerializers.config` ||
69
+
70
+ ## Renaming of class and modules
71
+
72
+ When moving some content to the new namespace we can find some names that does
73
+ not make much sense like `ActiveModel::Serializer::Adapter::JsonApi`.
74
+ Discussion of renaming existing classes / modules and JsonApi objects will
75
+ happen in separate pull requests, and issues, and in the google doc
76
+ https://docs.google.com/document/d/1rcrJr0sVcazY2Opd_6Kmv1iIwuHbI84s1P_NzFn-05c/edit?usp=sharing
77
+
78
+ Some of names already have a definition.
79
+
80
+ - Adapters get their own namespace under ActiveModelSerializers. E.g
81
+ `ActiveModelSerializers::Adapter`
82
+ - Serializers get their own namespace under ActiveModelSerializers. E.g
83
+ `ActiveModelSerializers::Serializer`
84
+
85
+ ## Keeping compatibility
86
+
87
+ All moved classes or modules be aliased to their old name and location with
88
+ deprecation warnings, such as
89
+ [was done for CollectionSerializer](https://github.com/rails-api/active_model_serializers/pull/1251).
90
+
91
+ # Drawbacks
92
+
93
+ This will be a breaking change, so all users serializers will be broken after a
94
+ major bump.
95
+ All pull requests will need to rebase since the architeture will change a lot.
96
+
97
+ # Alternatives
98
+
99
+ We can keep the way it is, and keep in mind to not add another namespace as a
100
+ public API.
101
+
102
+ # Unresolved questions
103
+
104
+ What is the better class name to be used to the class that will be inherited at
105
+ the creation of a serializer. This can be discussed in other RFC or directly via
106
+ pull request.
@@ -0,0 +1,15 @@
1
+ - Start Date: (YYYY-MM-DD)
2
+ - RFC PR: https://github.com/rails-api/active_model_serializers/pull/dddd
3
+ - ActiveModelSerializers Issue: https://github.com/rails-api/active_model_serializers/issues/dddd
4
+
5
+ # Summary
6
+
7
+ # Motivation
8
+
9
+ # Detailed design
10
+
11
+ # Drawbacks
12
+
13
+ # Alternatives
14
+
15
+ # Unresolved questions
@@ -0,0 +1,66 @@
1
+ require 'active_support/core_ext/class/attribute'
2
+ require 'active_model_serializers/serialization_context'
3
+
4
+ module ActionController
5
+ module Serialization
6
+ extend ActiveSupport::Concern
7
+
8
+ include ActionController::Renderers
9
+
10
+ module ClassMethods
11
+ def serialization_scope(scope)
12
+ self._serialization_scope = scope
13
+ end
14
+ end
15
+
16
+ included do
17
+ class_attribute :_serialization_scope
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
25
+ end
26
+
27
+ def serialization_scope
28
+ return unless _serialization_scope && respond_to?(_serialization_scope, true)
29
+
30
+ send(_serialization_scope)
31
+ end
32
+
33
+ def get_serializer(resource, options = {})
34
+ unless use_adapter?
35
+ warn 'ActionController::Serialization#use_adapter? has been removed. '\
36
+ "Please pass 'adapter: false' or see ActiveSupport::SerializableResource.new"
37
+ options[:adapter] = false
38
+ end
39
+
40
+ options.fetch(:namespace) { options[:namespace] = namespace_for_serializer }
41
+
42
+ serializable_resource = ActiveModelSerializers::SerializableResource.new(resource, options)
43
+ serializable_resource.serialization_scope ||= options.fetch(:scope) { serialization_scope }
44
+ serializable_resource.serialization_scope_name = options.fetch(:scope_name) { _serialization_scope }
45
+ # For compatibility with the JSON renderer: `json.to_json(options) if json.is_a?(String)`.
46
+ # Otherwise, since `serializable_resource` is not a string, the renderer would call
47
+ # `to_json` on a String and given odd results, such as `"".to_json #=> '""'`
48
+ serializable_resource.adapter.is_a?(String) ? serializable_resource.adapter : serializable_resource
49
+ end
50
+
51
+ # Deprecated
52
+ def use_adapter?
53
+ true
54
+ end
55
+
56
+ [:_render_option_json, :_render_with_renderer_json].each do |renderer_method|
57
+ define_method renderer_method do |resource, options|
58
+ options.fetch(:serialization_context) do
59
+ options[:serialization_context] = ActiveModelSerializers::SerializationContext.new(request, options)
60
+ end
61
+ serializable_resource = get_serializer(resource, options)
62
+ super(serializable_resource, options)
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,11 @@
1
+ require 'set'
2
+
3
+ module ActiveModel
4
+ class SerializableResource
5
+ class << self
6
+ extend ActiveModelSerializers::Deprecate
7
+
8
+ delegate_and_deprecate :new, ActiveModelSerializers::SerializableResource
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,231 @@
1
+ require 'thread_safe'
2
+ require 'jsonapi/include_directive'
3
+ require 'active_model/serializer/collection_serializer'
4
+ require 'active_model/serializer/array_serializer'
5
+ require 'active_model/serializer/error_serializer'
6
+ require 'active_model/serializer/errors_serializer'
7
+ require 'active_model/serializer/concerns/associations'
8
+ require 'active_model/serializer/concerns/attributes'
9
+ require 'active_model/serializer/concerns/caching'
10
+ require 'active_model/serializer/concerns/configuration'
11
+ require 'active_model/serializer/concerns/links'
12
+ require 'active_model/serializer/concerns/meta'
13
+ require 'active_model/serializer/concerns/type'
14
+ require 'active_model/serializer/fieldset'
15
+ require 'active_model/serializer/lint'
16
+
17
+ # ActiveModel::Serializer is an abstract class that is
18
+ # reified when subclassed to decorate a resource.
19
+ module ActiveModel
20
+ class Serializer
21
+ # @see #serializable_hash for more details on these valid keys.
22
+ SERIALIZABLE_HASH_VALID_KEYS = [:only, :except, :methods, :include, :root].freeze
23
+ extend ActiveSupport::Autoload
24
+ autoload :Adapter
25
+ autoload :Null
26
+ include Configuration
27
+ include Associations
28
+ include Attributes
29
+ include Caching
30
+ include Links
31
+ include Meta
32
+ include Type
33
+
34
+ # @param resource [ActiveRecord::Base, ActiveModelSerializers::Model]
35
+ # @return [ActiveModel::Serializer]
36
+ # Preferentially returns
37
+ # 1. resource.serializer
38
+ # 2. ArraySerializer when resource is a collection
39
+ # 3. options[:serializer]
40
+ # 4. lookup serializer when resource is a Class
41
+ def self.serializer_for(resource, options = {})
42
+ if resource.respond_to?(:serializer_class)
43
+ resource.serializer_class
44
+ elsif resource.respond_to?(:to_ary)
45
+ config.collection_serializer
46
+ else
47
+ options.fetch(:serializer) { get_serializer_for(resource.class, options[:namespace]) }
48
+ end
49
+ end
50
+
51
+ # @see ActiveModelSerializers::Adapter.lookup
52
+ # Deprecated
53
+ def self.adapter
54
+ ActiveModelSerializers::Adapter.lookup(config.adapter)
55
+ end
56
+ class << self
57
+ extend ActiveModelSerializers::Deprecate
58
+ deprecate :adapter, 'ActiveModelSerializers::Adapter.configured_adapter'
59
+ end
60
+
61
+ # @api private
62
+ def self.serializer_lookup_chain_for(klass, namespace = nil)
63
+ lookups = ActiveModelSerializers.config.serializer_lookup_chain
64
+ Array[*lookups].flat_map do |lookup|
65
+ lookup.call(klass, self, namespace)
66
+ end.compact
67
+ end
68
+
69
+ # Used to cache serializer name => serializer class
70
+ # when looked up by Serializer.get_serializer_for.
71
+ def self.serializers_cache
72
+ @serializers_cache ||= ThreadSafe::Cache.new
73
+ end
74
+
75
+ # @api private
76
+ # Find a serializer from a class and caches the lookup.
77
+ # Preferentially returns:
78
+ # 1. class name appended with "Serializer"
79
+ # 2. try again with superclass, if present
80
+ # 3. nil
81
+ def self.get_serializer_for(klass, namespace = nil)
82
+ return nil unless config.serializer_lookup_enabled
83
+
84
+ cache_key = ActiveSupport::Cache.expand_cache_key(klass, namespace)
85
+ serializers_cache.fetch_or_store(cache_key) do
86
+ # NOTE(beauby): When we drop 1.9.3 support we can lazify the map for perfs.
87
+ lookup_chain = serializer_lookup_chain_for(klass, namespace)
88
+ serializer_class = lookup_chain.map(&:safe_constantize).find { |x| x && x < ActiveModel::Serializer }
89
+
90
+ if serializer_class
91
+ serializer_class
92
+ elsif klass.superclass
93
+ get_serializer_for(klass.superclass)
94
+ end
95
+ end
96
+ end
97
+
98
+ # @api private
99
+ def self.include_directive_from_options(options)
100
+ if options[:include_directive]
101
+ options[:include_directive]
102
+ elsif options[:include]
103
+ JSONAPI::IncludeDirective.new(options[:include], allow_wildcard: true)
104
+ else
105
+ ActiveModelSerializers.default_include_directive
106
+ end
107
+ end
108
+
109
+ # @api private
110
+ def self.serialization_adapter_instance
111
+ @serialization_adapter_instance ||= ActiveModelSerializers::Adapter::Attributes
112
+ end
113
+
114
+ attr_accessor :object, :root, :scope
115
+
116
+ # `scope_name` is set as :current_user by default in the controller.
117
+ # If the instance does not have a method named `scope_name`, it
118
+ # defines the method so that it calls the +scope+.
119
+ def initialize(object, options = {})
120
+ self.object = object
121
+ self.instance_options = options
122
+ self.root = instance_options[:root]
123
+ self.scope = instance_options[:scope]
124
+
125
+ return if !(scope_name = instance_options[:scope_name]) || respond_to?(scope_name)
126
+
127
+ define_singleton_method scope_name, -> { scope }
128
+ end
129
+
130
+ def success?
131
+ true
132
+ end
133
+
134
+ # @return [Hash] containing the attributes and first level
135
+ # associations, similar to how ActiveModel::Serializers::JSON is used
136
+ # in ActiveRecord::Base.
137
+ #
138
+ # TODO: Include <tt>ActiveModel::Serializers::JSON</tt>.
139
+ # So that the below is true:
140
+ # @param options [nil, Hash] The same valid options passed to `serializable_hash`
141
+ # (:only, :except, :methods, and :include).
142
+ #
143
+ # See
144
+ # https://github.com/rails/rails/blob/v5.0.0.beta2/activemodel/lib/active_model/serializers/json.rb#L17-L101
145
+ # https://github.com/rails/rails/blob/v5.0.0.beta2/activemodel/lib/active_model/serialization.rb#L85-L123
146
+ # https://github.com/rails/rails/blob/v5.0.0.beta2/activerecord/lib/active_record/serialization.rb#L11-L17
147
+ # https://github.com/rails/rails/blob/v5.0.0.beta2/activesupport/lib/active_support/core_ext/object/json.rb#L147-L162
148
+ #
149
+ # @example
150
+ # # The :only and :except options can be used to limit the attributes included, and work
151
+ # # similar to the attributes method.
152
+ # serializer.as_json(only: [:id, :name])
153
+ # serializer.as_json(except: [:id, :created_at, :age])
154
+ #
155
+ # # To include the result of some method calls on the model use :methods:
156
+ # serializer.as_json(methods: :permalink)
157
+ #
158
+ # # To include associations use :include:
159
+ # serializer.as_json(include: :posts)
160
+ # # Second level and higher order associations work as well:
161
+ # serializer.as_json(include: { posts: { include: { comments: { only: :body } }, only: :title } })
162
+ def serializable_hash(adapter_options = nil, options = {}, adapter_instance = self.class.serialization_adapter_instance)
163
+ adapter_options ||= {}
164
+ options[:include_directive] ||= ActiveModel::Serializer.include_directive_from_options(adapter_options)
165
+ cached_attributes = adapter_options[:cached_attributes] ||= {}
166
+ resource = fetch_attributes(options[:fields], cached_attributes, adapter_instance)
167
+ relationships = resource_relationships(adapter_options, options, adapter_instance)
168
+ resource.merge(relationships)
169
+ end
170
+ alias to_hash serializable_hash
171
+ alias to_h serializable_hash
172
+
173
+ # @see #serializable_hash
174
+ # TODO: When moving attributes adapter logic here, @see #serializable_hash
175
+ # So that the below is true:
176
+ # @param options [nil, Hash] The same valid options passed to `as_json`
177
+ # (:root, :only, :except, :methods, and :include).
178
+ # The default for `root` is nil.
179
+ # The default value for include_root is false. You can change it to true if the given
180
+ # JSON string includes a single root node.
181
+ def as_json(adapter_opts = nil)
182
+ serializable_hash(adapter_opts)
183
+ end
184
+
185
+ # Used by adapter as resource root.
186
+ def json_key
187
+ root || _type || object.class.model_name.to_s.underscore
188
+ end
189
+
190
+ def read_attribute_for_serialization(attr)
191
+ if respond_to?(attr)
192
+ send(attr)
193
+ else
194
+ object.read_attribute_for_serialization(attr)
195
+ end
196
+ end
197
+
198
+ # @api private
199
+ def resource_relationships(adapter_options, options, adapter_instance)
200
+ relationships = {}
201
+ include_directive = options.fetch(:include_directive)
202
+ associations(include_directive).each do |association|
203
+ adapter_opts = adapter_options.merge(include_directive: include_directive[association.key])
204
+ relationships[association.key] ||= relationship_value_for(association, adapter_opts, adapter_instance)
205
+ end
206
+
207
+ relationships
208
+ end
209
+
210
+ # @api private
211
+ def relationship_value_for(association, adapter_options, adapter_instance)
212
+ return association.options[:virtual_value] if association.options[:virtual_value]
213
+ association_serializer = association.serializer
214
+ association_object = association_serializer && association_serializer.object
215
+ return unless association_object
216
+
217
+ relationship_value = association_serializer.serializable_hash(adapter_options, {}, adapter_instance)
218
+
219
+ if association.options[:polymorphic] && relationship_value
220
+ polymorphic_type = association_object.class.name.underscore
221
+ relationship_value = { type: polymorphic_type, polymorphic_type.to_sym => relationship_value }
222
+ end
223
+
224
+ relationship_value
225
+ end
226
+
227
+ protected
228
+
229
+ attr_accessor :instance_options
230
+ end
231
+ end
@@ -0,0 +1,24 @@
1
+ require 'active_model_serializers/adapter'
2
+ require 'active_model_serializers/deprecate'
3
+
4
+ module ActiveModel
5
+ class Serializer
6
+ # @deprecated Use ActiveModelSerializers::Adapter instead
7
+ module Adapter
8
+ class << self
9
+ extend ActiveModelSerializers::Deprecate
10
+
11
+ DEPRECATED_METHODS = [:create, :adapter_class, :adapter_map, :adapters, :register, :lookup].freeze
12
+ DEPRECATED_METHODS.each do |method|
13
+ delegate_and_deprecate method, ActiveModelSerializers::Adapter
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ require 'active_model/serializer/adapter/base'
21
+ require 'active_model/serializer/adapter/null'
22
+ require 'active_model/serializer/adapter/attributes'
23
+ require 'active_model/serializer/adapter/json'
24
+ require 'active_model/serializer/adapter/json_api'