active_model_serializers 0.10.0 → 0.10.2
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +2 -4
- data/.travis.yml +1 -0
- data/CHANGELOG.md +39 -2
- data/Gemfile +1 -1
- data/README.md +21 -24
- data/Rakefile +3 -3
- data/active_model_serializers.gemspec +19 -23
- data/docs/general/adapters.md +4 -2
- data/docs/general/configuration_options.md +6 -1
- data/docs/general/deserialization.md +1 -1
- data/docs/general/fields.md +31 -0
- data/docs/general/rendering.md +7 -2
- data/docs/general/serializers.md +62 -3
- data/docs/howto/add_pagination_links.md +2 -3
- data/docs/integrations/ember-and-json-api.md +25 -10
- data/docs/jsonapi/schema.md +1 -1
- data/lib/action_controller/serialization.rb +4 -3
- data/lib/active_model/serializer/adapter/base.rb +2 -0
- data/lib/active_model/serializer/array_serializer.rb +8 -5
- data/lib/active_model/serializer/associations.rb +6 -7
- data/lib/active_model/serializer/belongs_to_reflection.rb +0 -3
- data/lib/active_model/serializer/caching.rb +67 -112
- data/lib/active_model/serializer/collection_serializer.rb +30 -10
- data/lib/active_model/serializer/configuration.rb +1 -0
- data/lib/active_model/serializer/error_serializer.rb +11 -7
- data/lib/active_model/serializer/errors_serializer.rb +25 -20
- data/lib/active_model/serializer/has_many_reflection.rb +0 -3
- data/lib/active_model/serializer/has_one_reflection.rb +0 -3
- data/lib/active_model/serializer/lint.rb +134 -130
- data/lib/active_model/serializer/reflection.rb +3 -3
- data/lib/active_model/serializer/version.rb +1 -1
- data/lib/active_model/serializer.rb +57 -15
- data/lib/active_model_serializers/adapter/attributes.rb +2 -67
- data/lib/active_model_serializers/adapter/base.rb +38 -38
- data/lib/active_model_serializers/adapter/json_api/link.rb +1 -1
- data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +8 -1
- data/lib/active_model_serializers/adapter/json_api.rb +36 -28
- data/lib/active_model_serializers/adapter.rb +6 -0
- data/lib/active_model_serializers/deprecate.rb +1 -2
- data/lib/active_model_serializers/deserialization.rb +2 -0
- data/lib/active_model_serializers/model.rb +3 -1
- data/lib/active_model_serializers/railtie.rb +3 -1
- data/lib/active_model_serializers/register_jsonapi_renderer.rb +44 -31
- data/lib/active_model_serializers/serialization_context.rb +10 -3
- data/lib/active_model_serializers.rb +6 -0
- data/lib/generators/rails/serializer_generator.rb +3 -3
- data/lib/grape/active_model_serializers.rb +7 -5
- data/lib/grape/formatters/active_model_serializers.rb +19 -2
- data/lib/grape/helpers/active_model_serializers.rb +1 -0
- data/test/action_controller/adapter_selector_test.rb +4 -4
- data/test/action_controller/explicit_serializer_test.rb +5 -4
- data/test/action_controller/json/include_test.rb +106 -27
- data/test/action_controller/json_api/errors_test.rb +6 -7
- data/test/action_controller/json_api/linked_test.rb +29 -24
- data/test/action_controller/json_api/pagination_test.rb +19 -19
- data/test/action_controller/serialization_test.rb +10 -7
- data/test/active_model_serializers/json_pointer_test.rb +15 -13
- data/test/active_model_serializers/key_transform_test.rb +254 -252
- data/test/active_model_serializers/model_test.rb +6 -4
- data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +143 -0
- data/test/active_model_serializers/serialization_context_test_isolated.rb +23 -10
- data/test/adapter/json/collection_test.rb +14 -0
- data/test/adapter/json/transform_test.rb +14 -14
- data/test/adapter/json_api/collection_test.rb +4 -3
- data/test/adapter/json_api/errors_test.rb +17 -19
- data/test/adapter/json_api/has_many_test.rb +18 -18
- data/test/adapter/json_api/json_api_test.rb +5 -7
- data/test/adapter/json_api/linked_test.rb +9 -6
- data/test/adapter/json_api/links_test.rb +3 -1
- data/test/adapter/json_api/pagination_links_test.rb +19 -7
- data/test/adapter/json_api/relationships_test.rb +9 -4
- data/test/adapter/json_api/resource_identifier_test.rb +7 -2
- data/test/adapter/json_api/resource_meta_test.rb +3 -3
- data/test/adapter/json_api/transform_test.rb +251 -250
- data/test/adapter/json_api/type_test.rb +1 -1
- data/test/adapter/json_test.rb +8 -7
- data/test/adapter/null_test.rb +1 -2
- data/test/adapter/polymorphic_test.rb +5 -5
- data/test/adapter_test.rb +1 -1
- data/test/benchmark/app.rb +1 -1
- data/test/benchmark/bm_caching.rb +15 -15
- data/test/benchmark/bm_transform.rb +16 -5
- data/test/benchmark/controllers.rb +16 -17
- data/test/benchmark/fixtures.rb +72 -72
- data/test/cache_test.rb +101 -45
- data/test/collection_serializer_test.rb +2 -2
- data/test/fixtures/poro.rb +8 -7
- data/test/grape_test.rb +152 -56
- data/test/lint_test.rb +1 -1
- data/test/logger_test.rb +13 -11
- data/test/serializable_resource_test.rb +18 -22
- data/test/serializers/associations_test.rb +10 -10
- data/test/serializers/attribute_test.rb +1 -1
- data/test/serializers/attributes_test.rb +1 -1
- data/test/serializers/fieldset_test.rb +1 -1
- data/test/serializers/meta_test.rb +12 -6
- data/test/serializers/root_test.rb +1 -1
- data/test/serializers/serializer_for_test.rb +3 -1
- data/test/support/isolated_unit.rb +5 -2
- data/test/support/rails5_shims.rb +8 -2
- data/test/support/rails_app.rb +0 -9
- data/test/support/serialization_testing.rb +7 -5
- metadata +54 -24
- data/.rubocop_todo.yml +0 -167
- data/lib/active_model/serializer/include_tree.rb +0 -111
- data/test/include_tree/from_include_args_test.rb +0 -26
- data/test/include_tree/from_string_test.rb +0 -94
- data/test/include_tree/include_args_to_hash_test.rb +0 -64
@@ -31,16 +31,27 @@ module ActiveModelSerializers
|
|
31
31
|
autoload :Error
|
32
32
|
autoload :Deserialization
|
33
33
|
|
34
|
+
def self.default_key_transform
|
35
|
+
:dash
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.fragment_cache(cached_hash, non_cached_hash, root = true)
|
39
|
+
core_cached = cached_hash.first
|
40
|
+
core_non_cached = non_cached_hash.first
|
41
|
+
no_root_cache = cached_hash.delete_if { |key, _value| key == core_cached[0] }
|
42
|
+
no_root_non_cache = non_cached_hash.delete_if { |key, _value| key == core_non_cached[0] }
|
43
|
+
cached_resource = (core_cached[1]) ? core_cached[1].deep_merge(core_non_cached[1]) : core_non_cached[1]
|
44
|
+
hash = root ? { root => cached_resource } : cached_resource
|
45
|
+
|
46
|
+
hash.deep_merge no_root_non_cache.deep_merge no_root_cache
|
47
|
+
end
|
48
|
+
|
34
49
|
def initialize(serializer, options = {})
|
35
50
|
super
|
36
|
-
@
|
51
|
+
@include_directive = JSONAPI::IncludeDirective.new(options[:include], allow_wildcard: true)
|
37
52
|
@fieldset = options[:fieldset] || ActiveModel::Serializer::Fieldset.new(options.delete(:fields))
|
38
53
|
end
|
39
54
|
|
40
|
-
def self.default_key_transform
|
41
|
-
:dash
|
42
|
-
end
|
43
|
-
|
44
55
|
# {http://jsonapi.org/format/#crud Requests are transactional, i.e. success or failure}
|
45
56
|
# {http://jsonapi.org/format/#document-top-level data and errors MUST NOT coexist in the same document.}
|
46
57
|
def serializable_hash(*)
|
@@ -52,6 +63,11 @@ module ActiveModelSerializers
|
|
52
63
|
self.class.transform_key_casing!(document, instance_options)
|
53
64
|
end
|
54
65
|
|
66
|
+
def fragment_cache(cached_hash, non_cached_hash)
|
67
|
+
root = !instance_options.include?(:include)
|
68
|
+
self.class.fragment_cache(cached_hash, non_cached_hash, root)
|
69
|
+
end
|
70
|
+
|
55
71
|
# {http://jsonapi.org/format/#document-top-level Primary data}
|
56
72
|
# definition:
|
57
73
|
# ☐ toplevel_data (required)
|
@@ -174,18 +190,6 @@ module ActiveModelSerializers
|
|
174
190
|
hash
|
175
191
|
end
|
176
192
|
|
177
|
-
def fragment_cache(cached_hash, non_cached_hash)
|
178
|
-
root = false if instance_options.include?(:include)
|
179
|
-
core_cached = cached_hash.first
|
180
|
-
core_non_cached = non_cached_hash.first
|
181
|
-
no_root_cache = cached_hash.delete_if { |key, _value| key == core_cached[0] }
|
182
|
-
no_root_non_cache = non_cached_hash.delete_if { |key, _value| key == core_non_cached[0] }
|
183
|
-
cached_resource = (core_cached[1]) ? core_cached[1].deep_merge(core_non_cached[1]) : core_non_cached[1]
|
184
|
-
hash = root ? { root => cached_resource } : cached_resource
|
185
|
-
|
186
|
-
hash.deep_merge no_root_non_cache.deep_merge no_root_cache
|
187
|
-
end
|
188
|
-
|
189
193
|
protected
|
190
194
|
|
191
195
|
attr_reader :fieldset
|
@@ -232,7 +236,7 @@ module ActiveModelSerializers
|
|
232
236
|
@included = []
|
233
237
|
@resource_identifiers = Set.new
|
234
238
|
serializers.each { |serializer| process_resource(serializer, true) }
|
235
|
-
serializers.each { |serializer| process_relationships(serializer, @
|
239
|
+
serializers.each { |serializer| process_relationships(serializer, @include_directive) }
|
236
240
|
|
237
241
|
[@primary, @included]
|
238
242
|
end
|
@@ -251,21 +255,21 @@ module ActiveModelSerializers
|
|
251
255
|
true
|
252
256
|
end
|
253
257
|
|
254
|
-
def process_relationships(serializer,
|
255
|
-
serializer.associations(
|
256
|
-
process_relationship(association.serializer,
|
258
|
+
def process_relationships(serializer, include_directive)
|
259
|
+
serializer.associations(include_directive).each do |association|
|
260
|
+
process_relationship(association.serializer, include_directive[association.key])
|
257
261
|
end
|
258
262
|
end
|
259
263
|
|
260
|
-
def process_relationship(serializer,
|
264
|
+
def process_relationship(serializer, include_directive)
|
261
265
|
if serializer.respond_to?(:each)
|
262
|
-
serializer.each { |s| process_relationship(s,
|
266
|
+
serializer.each { |s| process_relationship(s, include_directive) }
|
263
267
|
return
|
264
268
|
end
|
265
269
|
return unless serializer && serializer.object
|
266
270
|
return unless process_resource(serializer, false)
|
267
271
|
|
268
|
-
process_relationships(serializer,
|
272
|
+
process_relationships(serializer, include_directive)
|
269
273
|
end
|
270
274
|
|
271
275
|
# {http://jsonapi.org/format/#document-resource-object-attributes Document Resource Object Attributes}
|
@@ -290,7 +294,7 @@ module ActiveModelSerializers
|
|
290
294
|
|
291
295
|
# {http://jsonapi.org/format/#document-resource-objects Document Resource Objects}
|
292
296
|
def resource_object_for(serializer)
|
293
|
-
resource_object =
|
297
|
+
resource_object = serializer.fetch(self) do
|
294
298
|
resource_object = ResourceIdentifier.new(serializer, instance_options).as_json
|
295
299
|
|
296
300
|
requested_fields = fieldset && fieldset.fields_for(resource_object[:type])
|
@@ -429,8 +433,11 @@ module ActiveModelSerializers
|
|
429
433
|
# meta: meta
|
430
434
|
# }.reject! {|_,v| v.nil? }
|
431
435
|
def relationships_for(serializer, requested_associations)
|
432
|
-
|
433
|
-
|
436
|
+
include_directive = JSONAPI::IncludeDirective.new(
|
437
|
+
requested_associations,
|
438
|
+
allow_wildcard: true
|
439
|
+
)
|
440
|
+
serializer.associations(include_directive).each_with_object({}) do |association, hash|
|
434
441
|
hash[association.key] = Relationship.new(
|
435
442
|
serializer,
|
436
443
|
association.serializer,
|
@@ -467,7 +474,8 @@ module ActiveModelSerializers
|
|
467
474
|
# }.reject! {|_,v| v.nil? }
|
468
475
|
def links_for(serializer)
|
469
476
|
serializer._links.each_with_object({}) do |(name, value), hash|
|
470
|
-
|
477
|
+
result = Link.new(serializer, value).as_json
|
478
|
+
hash[name] = result if result
|
471
479
|
end
|
472
480
|
end
|
473
481
|
|
@@ -5,11 +5,13 @@ module ActiveModelSerializers
|
|
5
5
|
private_constant :ADAPTER_MAP if defined?(private_constant)
|
6
6
|
|
7
7
|
class << self # All methods are class functions
|
8
|
+
# :nocov:
|
8
9
|
def new(*args)
|
9
10
|
fail ArgumentError, 'Adapters inherit from Adapter::Base.' \
|
10
11
|
"Adapter.new called with args: '#{args.inspect}', from" \
|
11
12
|
"'caller[0]'."
|
12
13
|
end
|
14
|
+
# :nocov:
|
13
15
|
|
14
16
|
def configured_adapter
|
15
17
|
lookup(ActiveModelSerializers.config.adapter)
|
@@ -51,6 +53,10 @@ module ActiveModelSerializers
|
|
51
53
|
self
|
52
54
|
end
|
53
55
|
|
56
|
+
def registered_name(adapter_class)
|
57
|
+
ADAPTER_MAP.key adapter_class
|
58
|
+
end
|
59
|
+
|
54
60
|
# @param adapter [String, Symbol, Class] name to fetch adapter by
|
55
61
|
# @return [ActiveModelSerializers::Adapter] subclass of Adapter
|
56
62
|
# @raise [UnknownAdapterError]
|
@@ -36,8 +36,7 @@ module ActiveModelSerializers
|
|
36
36
|
target = is_a?(Module) ? "#{self}." : "#{self.class}#"
|
37
37
|
msg = ["NOTE: #{target}#{name} is deprecated",
|
38
38
|
replacement == :none ? ' with no replacement' : "; use #{replacement} instead",
|
39
|
-
"\n#{target}#{name} called from #{ActiveModelSerializers.location_of_caller.join(
|
40
|
-
]
|
39
|
+
"\n#{target}#{name} called from #{ActiveModelSerializers.location_of_caller.join(':')}"]
|
41
40
|
warn "#{msg.join}."
|
42
41
|
send old, *args, &block
|
43
42
|
end
|
@@ -21,7 +21,7 @@ module ActiveModelSerializers
|
|
21
21
|
|
22
22
|
# Defaults to the downcased model name and updated_at
|
23
23
|
def cache_key
|
24
|
-
attributes.fetch(:cache_key) { "#{self.class.name.downcase}/#{id}-#{updated_at.strftime(
|
24
|
+
attributes.fetch(:cache_key) { "#{self.class.name.downcase}/#{id}-#{updated_at.strftime('%Y%m%d%H%M%S%9N')}" }
|
25
25
|
end
|
26
26
|
|
27
27
|
# Defaults to the time the serializer file was modified.
|
@@ -38,6 +38,7 @@ module ActiveModelSerializers
|
|
38
38
|
end
|
39
39
|
|
40
40
|
# The following methods are needed to be minimally implemented for ActiveModel::Errors
|
41
|
+
# :nocov:
|
41
42
|
def self.human_attribute_name(attr, _options = {})
|
42
43
|
attr
|
43
44
|
end
|
@@ -45,5 +46,6 @@ module ActiveModelSerializers
|
|
45
46
|
def self.lookup_ancestors
|
46
47
|
[self]
|
47
48
|
end
|
49
|
+
# :nocov:
|
48
50
|
end
|
49
51
|
end
|
@@ -23,7 +23,7 @@ module ActiveModelSerializers
|
|
23
23
|
# This hook is run after the action_controller railtie has set the configuration
|
24
24
|
# based on the *environment* configuration and before any config/initializers are run
|
25
25
|
# and also before eager_loading (if enabled).
|
26
|
-
initializer 'active_model_serializers.set_configs', :
|
26
|
+
initializer 'active_model_serializers.set_configs', after: 'action_controller.set_configs' do
|
27
27
|
ActiveModelSerializers.logger = Rails.configuration.action_controller.logger
|
28
28
|
ActiveModelSerializers.config.perform_caching = Rails.configuration.action_controller.perform_caching
|
29
29
|
# We want this hook to run after the config has been set, even if ActionController has already loaded.
|
@@ -32,11 +32,13 @@ module ActiveModelSerializers
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
+
# :nocov:
|
35
36
|
generators do |app|
|
36
37
|
Rails::Generators.configure!(app.config.generators)
|
37
38
|
Rails::Generators.hidden_namespaces.uniq!
|
38
39
|
require 'generators/rails/resource_override'
|
39
40
|
end
|
41
|
+
# :nocov:
|
40
42
|
|
41
43
|
if Rails.env.test?
|
42
44
|
ActionController::TestCase.send(:include, ActiveModelSerializers::Test::Schema)
|
@@ -22,44 +22,57 @@
|
|
22
22
|
# render jsonapi: model
|
23
23
|
#
|
24
24
|
# No wrapper format needed as it does not apply (i.e. no `wrap_parameters format: [jsonapi]`)
|
25
|
+
module ActiveModelSerializers
|
26
|
+
module Jsonapi
|
27
|
+
MEDIA_TYPE = 'application/vnd.api+json'.freeze
|
28
|
+
HEADERS = {
|
29
|
+
response: { 'CONTENT_TYPE'.freeze => MEDIA_TYPE },
|
30
|
+
request: { 'ACCEPT'.freeze => MEDIA_TYPE }
|
31
|
+
}.freeze
|
25
32
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
response: { 'CONTENT_TYPE'.freeze => MEDIA_TYPE },
|
30
|
-
request: { 'ACCEPT'.freeze => MEDIA_TYPE }
|
31
|
-
}.freeze
|
32
|
-
module ControllerSupport
|
33
|
-
def serialize_jsonapi(json, options)
|
34
|
-
options[:adapter] = :json_api
|
35
|
-
options.fetch(:serialization_context) { options[:serialization_context] = ActiveModelSerializers::SerializationContext.new(request) }
|
36
|
-
get_serializer(json, options)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
33
|
+
def self.install
|
34
|
+
# actionpack/lib/action_dispatch/http/mime_types.rb
|
35
|
+
Mime::Type.register MEDIA_TYPE, :jsonapi
|
40
36
|
|
41
|
-
|
42
|
-
|
37
|
+
if Rails::VERSION::MAJOR >= 5
|
38
|
+
ActionDispatch::Request.parameter_parsers[:jsonapi] = parser
|
39
|
+
else
|
40
|
+
ActionDispatch::ParamsParser::DEFAULT_PARSERS[Mime[:jsonapi]] = parser
|
41
|
+
end
|
43
42
|
|
44
|
-
|
45
|
-
|
43
|
+
# ref https://github.com/rails/rails/pull/21496
|
44
|
+
ActionController::Renderers.add :jsonapi do |json, options|
|
45
|
+
json = serialize_jsonapi(json, options).to_json(options) unless json.is_a?(String)
|
46
|
+
self.content_type ||= Mime[:jsonapi]
|
47
|
+
self.response_body = json
|
48
|
+
end
|
49
|
+
end
|
46
50
|
|
47
|
-
# Proposal: should actually deserialize the JSON API params
|
48
|
-
# to the hash format expected by `ActiveModel::Serializers::JSON`
|
49
|
-
# actionpack/lib/action_dispatch/http/parameters.rb
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
51
|
+
# Proposal: should actually deserialize the JSON API params
|
52
|
+
# to the hash format expected by `ActiveModel::Serializers::JSON`
|
53
|
+
# actionpack/lib/action_dispatch/http/parameters.rb
|
54
|
+
def self.parser
|
55
|
+
lambda do |body|
|
56
|
+
data = JSON.parse(body)
|
57
|
+
data = { _json: data } unless data.is_a?(Hash)
|
58
|
+
data.with_indifferent_access
|
59
|
+
end
|
60
|
+
end
|
55
61
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
62
|
+
module ControllerSupport
|
63
|
+
def serialize_jsonapi(json, options)
|
64
|
+
options[:adapter] = :json_api
|
65
|
+
options.fetch(:serialization_context) do
|
66
|
+
options[:serialization_context] = ActiveModelSerializers::SerializationContext.new(request)
|
67
|
+
end
|
68
|
+
get_serializer(json, options)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
61
72
|
end
|
62
73
|
|
74
|
+
ActiveModelSerializers::Jsonapi.install
|
75
|
+
|
63
76
|
ActiveSupport.on_load(:action_controller) do
|
64
77
|
include ActiveModelSerializers::Jsonapi::ControllerSupport
|
65
78
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'active_support/core_ext/array/extract_options'
|
1
2
|
module ActiveModelSerializers
|
2
3
|
class SerializationContext
|
3
4
|
class << self
|
@@ -22,9 +23,15 @@ module ActiveModelSerializers
|
|
22
23
|
|
23
24
|
attr_reader :request_url, :query_parameters, :key_transform
|
24
25
|
|
25
|
-
def initialize(
|
26
|
-
|
27
|
-
|
26
|
+
def initialize(*args)
|
27
|
+
options = args.extract_options!
|
28
|
+
if args.size == 1
|
29
|
+
request = args.pop
|
30
|
+
options[:request_url] = request.original_url[/\A[^?]+/]
|
31
|
+
options[:query_parameters] = request.query_parameters
|
32
|
+
end
|
33
|
+
@request_url = options.delete(:request_url)
|
34
|
+
@query_parameters = options.delete(:query_parameters)
|
28
35
|
@url_helpers = options.delete(:url_helpers) || self.class.url_helpers
|
29
36
|
@default_url_options = options.delete(:default_url_options) || self.class.default_url_options
|
30
37
|
end
|
@@ -31,6 +31,12 @@ module ActiveModelSerializers
|
|
31
31
|
[file, lineno]
|
32
32
|
end
|
33
33
|
|
34
|
+
# Memoized default include directive
|
35
|
+
# @return [JSONAPI::IncludeDirective]
|
36
|
+
def self.default_include_directive
|
37
|
+
@default_include_directive ||= JSONAPI::IncludeDirective.new(config.default_includes, allow_wildcard: true)
|
38
|
+
end
|
39
|
+
|
34
40
|
require 'active_model/serializer/version'
|
35
41
|
require 'active_model/serializer'
|
36
42
|
require 'active_model/serializable_resource'
|
@@ -2,11 +2,11 @@ module Rails
|
|
2
2
|
module Generators
|
3
3
|
class SerializerGenerator < NamedBase
|
4
4
|
source_root File.expand_path('../templates', __FILE__)
|
5
|
-
check_class_collision :
|
5
|
+
check_class_collision suffix: 'Serializer'
|
6
6
|
|
7
|
-
argument :attributes, :
|
7
|
+
argument :attributes, type: :array, default: [], banner: 'field:type field:type'
|
8
8
|
|
9
|
-
class_option :parent, :
|
9
|
+
class_option :parent, type: :string, desc: 'The parent class for the generated serializer'
|
10
10
|
|
11
11
|
def create_serializer_file
|
12
12
|
template 'serializer.rb.erb', File.join('app/serializers', class_path, "#{file_name}_serializer.rb")
|
@@ -4,11 +4,13 @@ require 'active_model_serializers'
|
|
4
4
|
require 'grape/formatters/active_model_serializers'
|
5
5
|
require 'grape/helpers/active_model_serializers'
|
6
6
|
|
7
|
-
module Grape
|
8
|
-
|
7
|
+
module Grape
|
8
|
+
module ActiveModelSerializers
|
9
|
+
extend ActiveSupport::Concern
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
11
|
+
included do
|
12
|
+
formatter :json, Grape::Formatters::ActiveModelSerializers
|
13
|
+
helpers Grape::Helpers::ActiveModelSerializers
|
14
|
+
end
|
13
15
|
end
|
14
16
|
end
|
@@ -2,14 +2,31 @@
|
|
2
2
|
#
|
3
3
|
# Serializer options can be passed as a hash from your Grape endpoint using env[:active_model_serializer_options],
|
4
4
|
# or better yet user the render helper in Grape::Helpers::ActiveModelSerializers
|
5
|
+
|
6
|
+
require 'active_model_serializers/serialization_context'
|
7
|
+
|
5
8
|
module Grape
|
6
9
|
module Formatters
|
7
10
|
module ActiveModelSerializers
|
8
11
|
def self.call(resource, env)
|
9
|
-
serializer_options =
|
10
|
-
serializer_options.merge!(env[:active_model_serializer_options]) if env[:active_model_serializer_options]
|
12
|
+
serializer_options = build_serializer_options(env)
|
11
13
|
::ActiveModelSerializers::SerializableResource.new(resource, serializer_options).to_json
|
12
14
|
end
|
15
|
+
|
16
|
+
def self.build_serializer_options(env)
|
17
|
+
ams_options = env[:active_model_serializer_options] || {}
|
18
|
+
|
19
|
+
# Add serialization context
|
20
|
+
ams_options.fetch(:serialization_context) do
|
21
|
+
request = env['grape.request']
|
22
|
+
ams_options[:serialization_context] = ::ActiveModelSerializers::SerializationContext.new(
|
23
|
+
request_url: request.url[/\A[^?]+/],
|
24
|
+
query_parameters: request.params
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
ams_options
|
29
|
+
end
|
13
30
|
end
|
14
31
|
end
|
15
32
|
end
|
@@ -5,17 +5,17 @@ module ActionController
|
|
5
5
|
class AdapterSelectorTest < ActionController::TestCase
|
6
6
|
class AdapterSelectorTestController < ActionController::Base
|
7
7
|
def render_using_default_adapter
|
8
|
-
@profile = Profile.new(
|
8
|
+
@profile = Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1')
|
9
9
|
render json: @profile
|
10
10
|
end
|
11
11
|
|
12
12
|
def render_using_adapter_override
|
13
|
-
@profile = Profile.new(
|
13
|
+
@profile = Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1')
|
14
14
|
render json: @profile, adapter: :json_api
|
15
15
|
end
|
16
16
|
|
17
17
|
def render_skipping_adapter
|
18
|
-
@profile = Profile.new(
|
18
|
+
@profile = Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1')
|
19
19
|
render json: @profile, adapter: false
|
20
20
|
end
|
21
21
|
end
|
@@ -32,7 +32,7 @@ module ActionController
|
|
32
32
|
|
33
33
|
expected = {
|
34
34
|
data: {
|
35
|
-
id:
|
35
|
+
id: @controller.instance_variable_get(:@profile).id.to_s,
|
36
36
|
type: 'profiles',
|
37
37
|
attributes: {
|
38
38
|
name: 'Name 1',
|
@@ -100,11 +100,12 @@ module ActionController
|
|
100
100
|
get :render_array_using_explicit_serializer_and_custom_serializers
|
101
101
|
|
102
102
|
expected = [
|
103
|
-
{
|
103
|
+
{
|
104
|
+
'title' => 'New Post',
|
104
105
|
'body' => 'Body',
|
105
|
-
'id' =>
|
106
|
+
'id' => @controller.instance_variable_get(:@post).id,
|
106
107
|
'comments' => [{ 'id' => 1 }, { 'id' => 2 }],
|
107
|
-
'author' => { 'id' =>
|
108
|
+
'author' => { 'id' => @controller.instance_variable_get(:@author).id }
|
108
109
|
}
|
109
110
|
]
|
110
111
|
|
@@ -122,7 +123,7 @@ module ActionController
|
|
122
123
|
id: 42,
|
123
124
|
lat: '-23.550520',
|
124
125
|
lng: '-46.633309',
|
125
|
-
|
126
|
+
address: 'Nowhere' # is a virtual attribute on LocationSerializer
|
126
127
|
}
|
127
128
|
]
|
128
129
|
}
|