active_model_serializers 0.10.3 → 0.10.12

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 (224) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +154 -2
  3. data/README.md +153 -15
  4. data/lib/action_controller/serialization.rb +11 -1
  5. data/lib/active_model/serializable_resource.rb +2 -0
  6. data/lib/active_model/serializer.rb +275 -81
  7. data/lib/active_model/serializer/adapter.rb +2 -0
  8. data/lib/active_model/serializer/adapter/attributes.rb +2 -0
  9. data/lib/active_model/serializer/adapter/base.rb +2 -0
  10. data/lib/active_model/serializer/adapter/json.rb +2 -0
  11. data/lib/active_model/serializer/adapter/json_api.rb +2 -0
  12. data/lib/active_model/serializer/adapter/null.rb +2 -0
  13. data/lib/active_model/serializer/array_serializer.rb +2 -0
  14. data/lib/active_model/serializer/association.rb +53 -14
  15. data/lib/active_model/serializer/attribute.rb +2 -0
  16. data/lib/active_model/serializer/belongs_to_reflection.rb +7 -1
  17. data/lib/active_model/serializer/collection_serializer.rb +8 -5
  18. data/lib/active_model/serializer/concerns/caching.rb +36 -23
  19. data/lib/active_model/serializer/error_serializer.rb +2 -0
  20. data/lib/active_model/serializer/errors_serializer.rb +2 -0
  21. data/lib/active_model/serializer/field.rb +2 -0
  22. data/lib/active_model/serializer/fieldset.rb +3 -1
  23. data/lib/active_model/serializer/has_many_reflection.rb +6 -1
  24. data/lib/active_model/serializer/has_one_reflection.rb +3 -1
  25. data/lib/active_model/serializer/lazy_association.rb +99 -0
  26. data/lib/active_model/serializer/link.rb +23 -0
  27. data/lib/active_model/serializer/lint.rb +2 -0
  28. data/lib/active_model/serializer/null.rb +2 -0
  29. data/lib/active_model/serializer/reflection.rb +122 -73
  30. data/lib/active_model/serializer/version.rb +3 -1
  31. data/lib/active_model_serializers.rb +29 -11
  32. data/lib/active_model_serializers/adapter.rb +3 -1
  33. data/lib/active_model_serializers/adapter/attributes.rb +23 -0
  34. data/lib/active_model_serializers/adapter/base.rb +4 -2
  35. data/lib/active_model_serializers/adapter/json.rb +2 -0
  36. data/lib/active_model_serializers/adapter/json_api.rb +44 -26
  37. data/lib/active_model_serializers/adapter/json_api/deserialization.rb +4 -2
  38. data/lib/active_model_serializers/adapter/json_api/error.rb +2 -0
  39. data/lib/active_model_serializers/adapter/json_api/jsonapi.rb +2 -0
  40. data/lib/active_model_serializers/adapter/json_api/link.rb +2 -0
  41. data/lib/active_model_serializers/adapter/json_api/meta.rb +2 -0
  42. data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +42 -21
  43. data/lib/active_model_serializers/adapter/json_api/relationship.rb +52 -9
  44. data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +35 -18
  45. data/lib/active_model_serializers/adapter/null.rb +2 -0
  46. data/lib/active_model_serializers/callbacks.rb +2 -0
  47. data/lib/active_model_serializers/deprecate.rb +2 -0
  48. data/lib/active_model_serializers/deserialization.rb +2 -0
  49. data/lib/active_model_serializers/json_pointer.rb +2 -0
  50. data/lib/active_model_serializers/logging.rb +2 -0
  51. data/lib/active_model_serializers/lookup_chain.rb +2 -0
  52. data/lib/active_model_serializers/model.rb +111 -30
  53. data/lib/active_model_serializers/model/caching.rb +25 -0
  54. data/lib/active_model_serializers/railtie.rb +4 -0
  55. data/lib/active_model_serializers/register_jsonapi_renderer.rb +2 -0
  56. data/lib/active_model_serializers/serializable_resource.rb +4 -2
  57. data/lib/active_model_serializers/serialization_context.rb +2 -0
  58. data/lib/active_model_serializers/test.rb +2 -0
  59. data/lib/active_model_serializers/test/schema.rb +4 -2
  60. data/lib/active_model_serializers/test/serializer.rb +2 -0
  61. data/lib/generators/rails/resource_override.rb +3 -1
  62. data/lib/generators/rails/serializer_generator.rb +2 -0
  63. data/lib/grape/active_model_serializers.rb +2 -0
  64. data/lib/grape/formatters/active_model_serializers.rb +2 -0
  65. data/lib/grape/helpers/active_model_serializers.rb +2 -0
  66. data/lib/tasks/rubocop.rake +55 -0
  67. metadata +74 -291
  68. data/.github/ISSUE_TEMPLATE.md +0 -29
  69. data/.github/PULL_REQUEST_TEMPLATE.md +0 -15
  70. data/.gitignore +0 -35
  71. data/.rubocop.yml +0 -102
  72. data/.simplecov +0 -110
  73. data/.travis.yml +0 -51
  74. data/CODE_OF_CONDUCT.md +0 -74
  75. data/CONTRIBUTING.md +0 -105
  76. data/Gemfile +0 -56
  77. data/Rakefile +0 -103
  78. data/active_model_serializers.gemspec +0 -62
  79. data/appveyor.yml +0 -24
  80. data/bin/bench +0 -171
  81. data/bin/bench_regression +0 -316
  82. data/bin/serve_benchmark +0 -39
  83. data/docs/ARCHITECTURE.md +0 -125
  84. data/docs/README.md +0 -42
  85. data/docs/STYLE.md +0 -58
  86. data/docs/general/adapters.md +0 -247
  87. data/docs/general/caching.md +0 -58
  88. data/docs/general/configuration_options.md +0 -169
  89. data/docs/general/deserialization.md +0 -100
  90. data/docs/general/fields.md +0 -31
  91. data/docs/general/getting_started.md +0 -133
  92. data/docs/general/instrumentation.md +0 -40
  93. data/docs/general/key_transforms.md +0 -40
  94. data/docs/general/logging.md +0 -14
  95. data/docs/general/rendering.md +0 -294
  96. data/docs/general/serializers.md +0 -461
  97. data/docs/how-open-source-maintained.jpg +0 -0
  98. data/docs/howto/add_pagination_links.md +0 -138
  99. data/docs/howto/add_relationship_links.md +0 -137
  100. data/docs/howto/add_root_key.md +0 -55
  101. data/docs/howto/grape_integration.md +0 -42
  102. data/docs/howto/outside_controller_use.md +0 -65
  103. data/docs/howto/passing_arbitrary_options.md +0 -27
  104. data/docs/howto/serialize_poro.md +0 -32
  105. data/docs/howto/test.md +0 -154
  106. data/docs/howto/upgrade_from_0_8_to_0_10.md +0 -265
  107. data/docs/integrations/ember-and-json-api.md +0 -144
  108. data/docs/integrations/grape.md +0 -19
  109. data/docs/jsonapi/errors.md +0 -56
  110. data/docs/jsonapi/schema.md +0 -151
  111. data/docs/jsonapi/schema/schema.json +0 -366
  112. data/docs/rfcs/0000-namespace.md +0 -106
  113. data/docs/rfcs/template.md +0 -15
  114. data/lib/active_model/serializer/collection_reflection.rb +0 -7
  115. data/lib/active_model/serializer/concerns/associations.rb +0 -102
  116. data/lib/active_model/serializer/concerns/attributes.rb +0 -82
  117. data/lib/active_model/serializer/concerns/configuration.rb +0 -59
  118. data/lib/active_model/serializer/concerns/links.rb +0 -35
  119. data/lib/active_model/serializer/concerns/meta.rb +0 -29
  120. data/lib/active_model/serializer/concerns/type.rb +0 -25
  121. data/lib/active_model/serializer/singular_reflection.rb +0 -7
  122. data/lib/active_model_serializers/key_transform.rb +0 -74
  123. data/test/action_controller/adapter_selector_test.rb +0 -53
  124. data/test/action_controller/explicit_serializer_test.rb +0 -135
  125. data/test/action_controller/json/include_test.rb +0 -246
  126. data/test/action_controller/json_api/deserialization_test.rb +0 -112
  127. data/test/action_controller/json_api/errors_test.rb +0 -40
  128. data/test/action_controller/json_api/fields_test.rb +0 -57
  129. data/test/action_controller/json_api/linked_test.rb +0 -202
  130. data/test/action_controller/json_api/pagination_test.rb +0 -116
  131. data/test/action_controller/json_api/transform_test.rb +0 -181
  132. data/test/action_controller/lookup_proc_test.rb +0 -49
  133. data/test/action_controller/namespace_lookup_test.rb +0 -226
  134. data/test/action_controller/serialization_scope_name_test.rb +0 -229
  135. data/test/action_controller/serialization_test.rb +0 -472
  136. data/test/active_model_serializers/adapter_for_test.rb +0 -208
  137. data/test/active_model_serializers/json_pointer_test.rb +0 -22
  138. data/test/active_model_serializers/key_transform_test.rb +0 -297
  139. data/test/active_model_serializers/logging_test.rb +0 -77
  140. data/test/active_model_serializers/model_test.rb +0 -22
  141. data/test/active_model_serializers/railtie_test_isolated.rb +0 -63
  142. data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +0 -143
  143. data/test/active_model_serializers/serialization_context_test_isolated.rb +0 -71
  144. data/test/active_model_serializers/test/schema_test.rb +0 -130
  145. data/test/active_model_serializers/test/serializer_test.rb +0 -62
  146. data/test/active_record_test.rb +0 -9
  147. data/test/adapter/attributes_test.rb +0 -43
  148. data/test/adapter/deprecation_test.rb +0 -100
  149. data/test/adapter/json/belongs_to_test.rb +0 -45
  150. data/test/adapter/json/collection_test.rb +0 -104
  151. data/test/adapter/json/has_many_test.rb +0 -45
  152. data/test/adapter/json/transform_test.rb +0 -93
  153. data/test/adapter/json_api/belongs_to_test.rb +0 -155
  154. data/test/adapter/json_api/collection_test.rb +0 -96
  155. data/test/adapter/json_api/errors_test.rb +0 -76
  156. data/test/adapter/json_api/fields_test.rb +0 -88
  157. data/test/adapter/json_api/has_many_embed_ids_test.rb +0 -43
  158. data/test/adapter/json_api/has_many_explicit_serializer_test.rb +0 -96
  159. data/test/adapter/json_api/has_many_test.rb +0 -165
  160. data/test/adapter/json_api/has_one_test.rb +0 -80
  161. data/test/adapter/json_api/include_data_if_sideloaded_test.rb +0 -166
  162. data/test/adapter/json_api/json_api_test.rb +0 -33
  163. data/test/adapter/json_api/linked_test.rb +0 -413
  164. data/test/adapter/json_api/links_test.rb +0 -95
  165. data/test/adapter/json_api/pagination_links_test.rb +0 -193
  166. data/test/adapter/json_api/parse_test.rb +0 -137
  167. data/test/adapter/json_api/relationship_test.rb +0 -397
  168. data/test/adapter/json_api/resource_identifier_test.rb +0 -110
  169. data/test/adapter/json_api/resource_meta_test.rb +0 -100
  170. data/test/adapter/json_api/toplevel_jsonapi_test.rb +0 -82
  171. data/test/adapter/json_api/transform_test.rb +0 -504
  172. data/test/adapter/json_api/type_test.rb +0 -61
  173. data/test/adapter/json_test.rb +0 -46
  174. data/test/adapter/null_test.rb +0 -22
  175. data/test/adapter/polymorphic_test.rb +0 -171
  176. data/test/adapter_test.rb +0 -67
  177. data/test/array_serializer_test.rb +0 -22
  178. data/test/benchmark/app.rb +0 -65
  179. data/test/benchmark/benchmarking_support.rb +0 -67
  180. data/test/benchmark/bm_active_record.rb +0 -81
  181. data/test/benchmark/bm_adapter.rb +0 -38
  182. data/test/benchmark/bm_caching.rb +0 -119
  183. data/test/benchmark/bm_lookup_chain.rb +0 -83
  184. data/test/benchmark/bm_transform.rb +0 -45
  185. data/test/benchmark/config.ru +0 -3
  186. data/test/benchmark/controllers.rb +0 -83
  187. data/test/benchmark/fixtures.rb +0 -219
  188. data/test/cache_test.rb +0 -579
  189. data/test/collection_serializer_test.rb +0 -110
  190. data/test/fixtures/active_record.rb +0 -78
  191. data/test/fixtures/poro.rb +0 -286
  192. data/test/generators/scaffold_controller_generator_test.rb +0 -24
  193. data/test/generators/serializer_generator_test.rb +0 -74
  194. data/test/grape_test.rb +0 -178
  195. data/test/lint_test.rb +0 -49
  196. data/test/logger_test.rb +0 -20
  197. data/test/poro_test.rb +0 -9
  198. data/test/serializable_resource_test.rb +0 -79
  199. data/test/serializers/association_macros_test.rb +0 -37
  200. data/test/serializers/associations_test.rb +0 -370
  201. data/test/serializers/attribute_test.rb +0 -151
  202. data/test/serializers/attributes_test.rb +0 -52
  203. data/test/serializers/caching_configuration_test_isolated.rb +0 -170
  204. data/test/serializers/configuration_test.rb +0 -32
  205. data/test/serializers/fieldset_test.rb +0 -14
  206. data/test/serializers/meta_test.rb +0 -202
  207. data/test/serializers/options_test.rb +0 -21
  208. data/test/serializers/read_attribute_for_serialization_test.rb +0 -79
  209. data/test/serializers/root_test.rb +0 -21
  210. data/test/serializers/serialization_test.rb +0 -55
  211. data/test/serializers/serializer_for_test.rb +0 -136
  212. data/test/serializers/serializer_for_with_namespace_test.rb +0 -87
  213. data/test/support/custom_schemas/active_model_serializers/test/schema_test/my/index.json +0 -6
  214. data/test/support/isolated_unit.rb +0 -82
  215. data/test/support/rails5_shims.rb +0 -53
  216. data/test/support/rails_app.rb +0 -36
  217. data/test/support/schemas/active_model_serializers/test/schema_test/my/index.json +0 -6
  218. data/test/support/schemas/active_model_serializers/test/schema_test/my/show.json +0 -6
  219. data/test/support/schemas/custom/show.json +0 -7
  220. data/test/support/schemas/hyper_schema.json +0 -93
  221. data/test/support/schemas/render_using_json_api.json +0 -43
  222. data/test/support/schemas/simple_json_pointers.json +0 -10
  223. data/test/support/serialization_testing.rb +0 -71
  224. data/test/test_helper.rb +0 -58
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_model/serializer/field'
4
+
5
+ module ActiveModel
6
+ class Serializer
7
+ # Holds all the data about a serializer link
8
+ #
9
+ # @example
10
+ # class PostSerializer < ActiveModel::Serializer
11
+ # link :callback, if: :internal? do
12
+ # object.callback_link
13
+ # end
14
+ #
15
+ # def internal?
16
+ # instance_options[:internal] == true
17
+ # end
18
+ # end
19
+ #
20
+ class Link < Field
21
+ end
22
+ end
23
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveModel
2
4
  class Serializer
3
5
  module Lint
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveModel
2
4
  class Serializer
3
5
  class Null < Serializer
@@ -1,4 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_model/serializer/field'
4
+ require 'active_model/serializer/association'
2
5
 
3
6
  module ActiveModel
4
7
  class Serializer
@@ -8,12 +11,26 @@ module ActiveModel
8
11
  # @example
9
12
  # class PostSerializer < ActiveModel::Serializer
10
13
  # has_one :author, serializer: AuthorSerializer
14
+ # belongs_to :boss, type: :users, foreign_key: :boss_id
11
15
  # has_many :comments
12
16
  # has_many :comments, key: :last_comments do
13
17
  # object.comments.last(1)
14
18
  # end
15
19
  # has_many :secret_meta_data, if: :is_admin?
16
20
  #
21
+ # has_one :blog do |serializer|
22
+ # meta count: object.roles.count
23
+ # serializer.cached_blog
24
+ # end
25
+ #
26
+ # private
27
+ #
28
+ # def cached_blog
29
+ # cache_store.fetch("cached_blog:#{object.updated_at}") do
30
+ # Blog.find(object.blog_id)
31
+ # end
32
+ # end
33
+ #
17
34
  # def is_admin?
18
35
  # current_user.admin?
19
36
  # end
@@ -23,53 +40,122 @@ module ActiveModel
23
40
  # 1) as 'comments' and named 'comments'.
24
41
  # 2) as 'object.comments.last(1)' and named 'last_comments'.
25
42
  #
26
- # PostSerializer._reflections #=>
27
- # # [
28
- # # HasOneReflection.new(:author, serializer: AuthorSerializer),
29
- # # HasManyReflection.new(:comments)
30
- # # HasManyReflection.new(:comments, { key: :last_comments }, #<Block>)
31
- # # HasManyReflection.new(:secret_meta_data, { if: :is_admin? })
32
- # # ]
43
+ # PostSerializer._reflections # =>
44
+ # # {
45
+ # # author: HasOneReflection.new(:author, serializer: AuthorSerializer),
46
+ # # comments: HasManyReflection.new(:comments)
47
+ # # last_comments: HasManyReflection.new(:comments, { key: :last_comments }, #<Block>)
48
+ # # secret_meta_data: HasManyReflection.new(:secret_meta_data, { if: :is_admin? })
49
+ # # }
33
50
  #
34
51
  # So you can inspect reflections in your Adapters.
35
- #
36
52
  class Reflection < Field
53
+ attr_reader :foreign_key, :type
54
+
37
55
  def initialize(*)
38
56
  super
39
- @_links = {}
40
- @_include_data = Serializer.config.include_data_default
41
- @_meta = nil
57
+ options[:links] = {}
58
+ options[:include_data_setting] = Serializer.config.include_data_default
59
+ options[:meta] = nil
60
+ @type = options.fetch(:type) do
61
+ class_name = options.fetch(:class_name, name.to_s.camelize.singularize)
62
+ class_name.underscore.pluralize.to_sym
63
+ end
64
+ @foreign_key = options.fetch(:foreign_key) do
65
+ if collection?
66
+ "#{name.to_s.singularize}_ids".to_sym
67
+ else
68
+ "#{name}_id".to_sym
69
+ end
70
+ end
42
71
  end
43
72
 
73
+ # @api public
74
+ # @example
75
+ # has_one :blog do
76
+ # include_data false
77
+ # link :self, 'a link'
78
+ # link :related, 'another link'
79
+ # link :self, '//example.com/link_author/relationships/bio'
80
+ # id = object.profile.id
81
+ # link :related do
82
+ # "//example.com/profiles/#{id}" if id != 123
83
+ # end
84
+ # link :related do
85
+ # ids = object.likes.map(&:id).join(',')
86
+ # href "//example.com/likes/#{ids}"
87
+ # meta ids: ids
88
+ # end
89
+ # end
44
90
  def link(name, value = nil, &block)
45
- @_links[name] = block || value
91
+ options[:links][name] = block_given? ? block : value
46
92
  :nil
47
93
  end
48
94
 
95
+ # @api public
96
+ # @example
97
+ # has_one :blog do
98
+ # include_data false
99
+ # meta(id: object.blog.id)
100
+ # meta liked: object.likes.any?
101
+ # link :self do
102
+ # href object.blog.id.to_s
103
+ # meta(id: object.blog.id)
104
+ # end
49
105
  def meta(value = nil, &block)
50
- @_meta = block || value
106
+ options[:meta] = block_given? ? block : value
51
107
  :nil
52
108
  end
53
109
 
110
+ # @api public
111
+ # @example
112
+ # has_one :blog do
113
+ # include_data false
114
+ # link :self, 'a link'
115
+ # link :related, 'another link'
116
+ # end
117
+ #
118
+ # has_one :blog do
119
+ # include_data false
120
+ # link :self, 'a link'
121
+ # link :related, 'another link'
122
+ # end
123
+ #
124
+ # belongs_to :reviewer do
125
+ # meta name: 'Dan Brown'
126
+ # include_data true
127
+ # end
128
+ #
129
+ # has_many :tags, serializer: TagSerializer do
130
+ # link :self, '//example.com/link_author/relationships/tags'
131
+ # include_data :if_sideloaded
132
+ # end
54
133
  def include_data(value = true)
55
- @_include_data = value
134
+ options[:include_data_setting] = value
56
135
  :nil
57
136
  end
58
137
 
138
+ def collection?
139
+ false
140
+ end
141
+
142
+ def include_data?(include_slice)
143
+ include_data_setting = options[:include_data_setting]
144
+ case include_data_setting
145
+ when :if_sideloaded then include_slice.key?(options.fetch(:key, name))
146
+ when true then true
147
+ when false then false
148
+ else fail ArgumentError, "Unknown include_data_setting '#{include_data_setting.inspect}'"
149
+ end
150
+ end
151
+
59
152
  # @param serializer [ActiveModel::Serializer]
60
153
  # @yield [ActiveModel::Serializer]
61
154
  # @return [:nil, associated resource or resource collection]
62
- # @example
63
- # has_one :blog do |serializer|
64
- # serializer.cached_blog
65
- # end
66
- #
67
- # def cached_blog
68
- # cache_store.fetch("cached_blog:#{object.updated_at}") do
69
- # Blog.find(object.blog_id)
70
- # end
71
- # end
72
155
  def value(serializer, include_slice)
156
+ # NOTE(BF): This method isn't thread-safe because the _reflections class attribute is not thread-safe
157
+ # Therefore, when we build associations from reflections, we dup the entire reflection instance.
158
+ # Better solutions much appreciated!
73
159
  @object = serializer.object
74
160
  @scope = serializer.scope
75
161
 
@@ -83,6 +169,11 @@ module ActiveModel
83
169
  end
84
170
  end
85
171
 
172
+ # @api private
173
+ def foreign_key_on
174
+ :related
175
+ end
176
+
86
177
  # Build association. This method is used internally to
87
178
  # build serializer's association by its reflection.
88
179
  #
@@ -103,61 +194,19 @@ module ActiveModel
103
194
  # comments_reflection.build_association(post_serializer, foo: 'bar')
104
195
  #
105
196
  # @api private
106
- #
107
197
  def build_association(parent_serializer, parent_serializer_options, include_slice = {})
108
- reflection_options = options.dup
109
-
110
- # Pass the parent's namespace onto the child serializer
111
- reflection_options[:namespace] ||= parent_serializer_options[:namespace]
112
-
113
- association_value = value(parent_serializer, include_slice)
114
- serializer_class = parent_serializer.class.serializer_for(association_value, reflection_options)
115
- reflection_options[:include_data] = include_data?(include_slice)
116
- reflection_options[:links] = @_links
117
- reflection_options[:meta] = @_meta
118
-
119
- if serializer_class
120
- serializer = catch(:no_serializer) do
121
- serializer_class.new(
122
- association_value,
123
- serializer_options(parent_serializer, parent_serializer_options, reflection_options)
124
- )
125
- end
126
- if serializer.nil?
127
- reflection_options[:virtual_value] = association_value.try(:as_json) || association_value
128
- else
129
- reflection_options[:serializer] = serializer
130
- end
131
- elsif !association_value.nil? && !association_value.instance_of?(Object)
132
- reflection_options[:virtual_value] = association_value
133
- end
134
-
135
- block = nil
136
- Association.new(name, reflection_options, block)
198
+ association_options = {
199
+ parent_serializer: parent_serializer,
200
+ parent_serializer_options: parent_serializer_options,
201
+ include_slice: include_slice
202
+ }
203
+ Association.new(self, association_options)
137
204
  end
138
205
 
139
206
  protected
140
207
 
208
+ # used in instance exec
141
209
  attr_accessor :object, :scope
142
-
143
- private
144
-
145
- def include_data?(include_slice)
146
- if @_include_data == :if_sideloaded
147
- include_slice.key?(name)
148
- else
149
- @_include_data
150
- end
151
- end
152
-
153
- def serializer_options(parent_serializer, parent_serializer_options, reflection_options)
154
- serializer = reflection_options.fetch(:serializer, nil)
155
-
156
- serializer_options = parent_serializer_options.except(:serializer)
157
- serializer_options[:serializer] = serializer if serializer
158
- serializer_options[:serializer_context_class] = parent_serializer.class
159
- serializer_options
160
- end
161
210
  end
162
211
  end
163
212
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveModel
2
4
  class Serializer
3
- VERSION = '0.10.3'.freeze
5
+ VERSION = '0.10.12'.freeze
4
6
  end
5
7
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_model'
2
4
  require 'active_support'
3
5
  require 'active_support/core_ext/object/with_options'
@@ -5,16 +7,19 @@ require 'active_support/core_ext/string/inflections'
5
7
  require 'active_support/json'
6
8
  module ActiveModelSerializers
7
9
  extend ActiveSupport::Autoload
8
- autoload :Model
9
- autoload :Callbacks
10
- autoload :Deserialization
11
- autoload :SerializableResource
12
- autoload :Logging
13
- autoload :Test
14
- autoload :Adapter
15
- autoload :JsonPointer
16
- autoload :Deprecate
17
- autoload :LookupChain
10
+ eager_autoload do
11
+ autoload :Model
12
+ autoload :Callbacks
13
+ autoload :SerializableResource
14
+ autoload :SerializationContext
15
+ autoload :Logging
16
+ autoload :Test
17
+ autoload :Adapter
18
+ autoload :JsonPointer
19
+ autoload :Deprecate
20
+ autoload :LookupChain
21
+ autoload :Deserialization
22
+ end
18
23
 
19
24
  class << self; attr_accessor :logger; end
20
25
  self.logger = ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new(STDOUT))
@@ -38,8 +43,21 @@ module ActiveModelSerializers
38
43
  @default_include_directive ||= JSONAPI::IncludeDirective.new(config.default_includes, allow_wildcard: true)
39
44
  end
40
45
 
46
+ def self.silence_warnings
47
+ original_verbose = $VERBOSE
48
+ $VERBOSE = nil
49
+ yield
50
+ ensure
51
+ $VERBOSE = original_verbose
52
+ end
53
+
54
+ def self.eager_load!
55
+ super
56
+ ActiveModel::Serializer.eager_load!
57
+ end
58
+
41
59
  require 'active_model/serializer/version'
42
60
  require 'active_model/serializer'
43
61
  require 'active_model/serializable_resource'
44
- require 'active_model_serializers/railtie' if defined?(::Rails)
62
+ require 'active_model_serializers/railtie' if defined?(::Rails::Railtie)
45
63
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveModelSerializers
2
4
  module Adapter
3
5
  UnknownAdapterError = Class.new(ArgumentError)
@@ -35,7 +37,7 @@ module ActiveModelSerializers
35
37
 
36
38
  # @return [Array<Symbol>] list of adapter names
37
39
  def adapters
38
- adapter_map.keys.sort
40
+ adapter_map.keys.sort!
39
41
  end
40
42
 
41
43
  # Adds an adapter 'klass' with 'name' to the 'adapter_map'
@@ -1,6 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveModelSerializers
2
4
  module Adapter
3
5
  class Attributes < Base
6
+ def initialize(*)
7
+ super
8
+ instance_options[:fieldset] ||= ActiveModel::Serializer::Fieldset.new(fields_to_fieldset(instance_options.delete(:fields)))
9
+ end
10
+
4
11
  def serializable_hash(options = nil)
5
12
  options = serialization_options(options)
6
13
  options[:fields] ||= instance_options[:fields]
@@ -8,6 +15,22 @@ module ActiveModelSerializers
8
15
 
9
16
  self.class.transform_key_casing!(serialized_hash, instance_options)
10
17
  end
18
+
19
+ private
20
+
21
+ def fields_to_fieldset(fields)
22
+ return fields if fields.nil?
23
+ resource_fields = []
24
+ relationship_fields = {}
25
+ fields.each do |field|
26
+ case field
27
+ when Symbol, String then resource_fields << field
28
+ when Hash then relationship_fields.merge!(field)
29
+ else fail ArgumentError, "Unknown conversion of fields to fieldset: '#{field.inspect}' in '#{fields.inspect}'"
30
+ end
31
+ end
32
+ relationship_fields.merge!(serializer.json_key.to_sym => resource_fields)
33
+ end
11
34
  end
12
35
  end
13
36
  end
@@ -1,4 +1,6 @@
1
- require 'active_model_serializers/key_transform'
1
+ # frozen_string_literal: true
2
+
3
+ require 'case_transform'
2
4
 
3
5
  module ActiveModelSerializers
4
6
  module Adapter
@@ -31,7 +33,7 @@ module ActiveModelSerializers
31
33
  # @param options [Object] serializable resource options
32
34
  # @return [Symbol] the default transform for the adapter
33
35
  def self.transform_key_casing!(value, options)
34
- KeyTransform.send(transform(options), value)
36
+ CaseTransform.send(transform(options), value)
35
37
  end
36
38
 
37
39
  def self.cache_key
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveModelSerializers
2
4
  module Adapter
3
5
  class Json < Base
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # {http://jsonapi.org/format/ JSON API specification}
2
4
  # rubocop:disable Style/AsciiComments
3
5
  # TODO: implement!
@@ -22,14 +24,16 @@ module ActiveModelSerializers
22
24
  module Adapter
23
25
  class JsonApi < Base
24
26
  extend ActiveSupport::Autoload
25
- autoload :Jsonapi
26
- autoload :ResourceIdentifier
27
- autoload :Relationship
28
- autoload :Link
29
- autoload :PaginationLinks
30
- autoload :Meta
31
- autoload :Error
32
- autoload :Deserialization
27
+ eager_autoload do
28
+ autoload :Jsonapi
29
+ autoload :ResourceIdentifier
30
+ autoload :Link
31
+ autoload :PaginationLinks
32
+ autoload :Meta
33
+ autoload :Error
34
+ autoload :Deserialization
35
+ autoload :Relationship
36
+ end
33
37
 
34
38
  def self.default_key_transform
35
39
  :dash
@@ -257,7 +261,8 @@ module ActiveModelSerializers
257
261
 
258
262
  def process_relationships(serializer, include_slice)
259
263
  serializer.associations(include_slice).each do |association|
260
- process_relationship(association.serializer, include_slice[association.key])
264
+ # TODO(BF): Process relationship without evaluating lazy_association
265
+ process_relationship(association.lazy_association.serializer, include_slice[association.key])
261
266
  end
262
267
  end
263
268
 
@@ -294,20 +299,8 @@ module ActiveModelSerializers
294
299
 
295
300
  # {http://jsonapi.org/format/#document-resource-objects Document Resource Objects}
296
301
  def resource_object_for(serializer, include_slice = {})
297
- resource_object = serializer.fetch(self) do
298
- resource_object = ResourceIdentifier.new(serializer, instance_options).as_json
302
+ resource_object = data_for(serializer, include_slice)
299
303
 
300
- requested_fields = fieldset && fieldset.fields_for(resource_object[:type])
301
- attributes = attributes_for(serializer, requested_fields)
302
- resource_object[:attributes] = attributes if attributes.any?
303
- resource_object
304
- end
305
-
306
- requested_associations = fieldset.fields_for(resource_object[:type]) || '*'
307
- relationships = relationships_for(serializer, requested_associations, include_slice)
308
- resource_object[:relationships] = relationships if relationships.any?
309
-
310
- links = links_for(serializer)
311
304
  # toplevel_links
312
305
  # definition:
313
306
  # allOf
@@ -321,7 +314,10 @@ module ActiveModelSerializers
321
314
  # prs:
322
315
  # https://github.com/rails-api/active_model_serializers/pull/1247
323
316
  # https://github.com/rails-api/active_model_serializers/pull/1018
324
- resource_object[:links] = links if links.any?
317
+ if (links = links_for(serializer)).any?
318
+ resource_object ||= {}
319
+ resource_object[:links] = links
320
+ end
325
321
 
326
322
  # toplevel_meta
327
323
  # alias meta
@@ -331,12 +327,33 @@ module ActiveModelSerializers
331
327
  # {
332
328
  # :'git-ref' => 'abc123'
333
329
  # }
334
- meta = meta_for(serializer)
335
- resource_object[:meta] = meta unless meta.blank?
330
+ if (meta = meta_for(serializer)).present?
331
+ resource_object ||= {}
332
+ resource_object[:meta] = meta
333
+ end
336
334
 
337
335
  resource_object
338
336
  end
339
337
 
338
+ def data_for(serializer, include_slice)
339
+ data = serializer.fetch(self) do
340
+ resource_object = ResourceIdentifier.new(serializer, instance_options).as_json
341
+ break nil if resource_object.nil?
342
+
343
+ requested_fields = fieldset && fieldset.fields_for(resource_object[:type])
344
+ attributes = attributes_for(serializer, requested_fields)
345
+ resource_object[:attributes] = attributes if attributes.any?
346
+ resource_object
347
+ end
348
+ data.tap do |resource_object|
349
+ next if resource_object.nil?
350
+ # NOTE(BF): the attributes are cached above, separately from the relationships, below.
351
+ requested_associations = fieldset.fields_for(resource_object[:type]) || '*'
352
+ relationships = relationships_for(serializer, requested_associations, include_slice)
353
+ resource_object[:relationships] = relationships if relationships.any?
354
+ end
355
+ end
356
+
340
357
  # {http://jsonapi.org/format/#document-resource-object-relationships Document Resource Object Relationship}
341
358
  # relationships
342
359
  # definition:
@@ -467,7 +484,8 @@ module ActiveModelSerializers
467
484
  # }.reject! {|_,v| v.nil? }
468
485
  def links_for(serializer)
469
486
  serializer._links.each_with_object({}) do |(name, value), hash|
470
- result = Link.new(serializer, value).as_json
487
+ next if value.excluded?(serializer)
488
+ result = Link.new(serializer, value.block).as_json
471
489
  hash[name] = result if result
472
490
  end
473
491
  end