active_model_serializers_custom 0.10.90
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 +7 -0
- data/.github/ISSUE_TEMPLATE.md +29 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +15 -0
- data/.gitignore +35 -0
- data/.rubocop.yml +109 -0
- data/.simplecov +110 -0
- data/.travis.yml +63 -0
- data/CHANGELOG.md +727 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/CONTRIBUTING.md +105 -0
- data/Gemfile +74 -0
- data/MIT-LICENSE +22 -0
- data/README.md +305 -0
- data/Rakefile +76 -0
- data/active_model_serializers.gemspec +64 -0
- data/appveyor.yml +28 -0
- data/bin/bench +171 -0
- data/bin/bench_regression +316 -0
- data/bin/rubocop +38 -0
- data/bin/serve_benchmark +39 -0
- data/docs/README.md +41 -0
- data/docs/STYLE.md +58 -0
- data/docs/general/adapters.md +269 -0
- data/docs/general/caching.md +58 -0
- data/docs/general/configuration_options.md +185 -0
- data/docs/general/deserialization.md +100 -0
- data/docs/general/fields.md +31 -0
- data/docs/general/getting_started.md +133 -0
- data/docs/general/instrumentation.md +40 -0
- data/docs/general/key_transforms.md +40 -0
- data/docs/general/logging.md +21 -0
- data/docs/general/rendering.md +293 -0
- data/docs/general/serializers.md +495 -0
- data/docs/how-open-source-maintained.jpg +0 -0
- data/docs/howto/add_pagination_links.md +138 -0
- data/docs/howto/add_relationship_links.md +140 -0
- data/docs/howto/add_root_key.md +62 -0
- data/docs/howto/grape_integration.md +42 -0
- data/docs/howto/outside_controller_use.md +66 -0
- data/docs/howto/passing_arbitrary_options.md +27 -0
- data/docs/howto/serialize_poro.md +73 -0
- data/docs/howto/test.md +154 -0
- data/docs/howto/upgrade_from_0_8_to_0_10.md +265 -0
- data/docs/integrations/ember-and-json-api.md +147 -0
- data/docs/integrations/grape.md +19 -0
- data/docs/jsonapi/errors.md +56 -0
- data/docs/jsonapi/schema.md +151 -0
- data/docs/jsonapi/schema/schema.json +366 -0
- data/docs/rfcs/0000-namespace.md +106 -0
- data/docs/rfcs/template.md +15 -0
- data/lib/action_controller/serialization.rb +76 -0
- data/lib/active_model/serializable_resource.rb +13 -0
- data/lib/active_model/serializer.rb +418 -0
- data/lib/active_model/serializer/adapter.rb +26 -0
- data/lib/active_model/serializer/adapter/attributes.rb +17 -0
- data/lib/active_model/serializer/adapter/base.rb +20 -0
- data/lib/active_model/serializer/adapter/json.rb +17 -0
- data/lib/active_model/serializer/adapter/json_api.rb +17 -0
- data/lib/active_model/serializer/adapter/null.rb +17 -0
- data/lib/active_model/serializer/array_serializer.rb +14 -0
- data/lib/active_model/serializer/association.rb +91 -0
- data/lib/active_model/serializer/attribute.rb +27 -0
- data/lib/active_model/serializer/belongs_to_reflection.rb +13 -0
- data/lib/active_model/serializer/collection_serializer.rb +90 -0
- data/lib/active_model/serializer/concerns/caching.rb +304 -0
- data/lib/active_model/serializer/error_serializer.rb +16 -0
- data/lib/active_model/serializer/errors_serializer.rb +34 -0
- data/lib/active_model/serializer/field.rb +92 -0
- data/lib/active_model/serializer/fieldset.rb +33 -0
- data/lib/active_model/serializer/has_many_reflection.rb +12 -0
- data/lib/active_model/serializer/has_one_reflection.rb +9 -0
- data/lib/active_model/serializer/lazy_association.rb +99 -0
- data/lib/active_model/serializer/link.rb +23 -0
- data/lib/active_model/serializer/lint.rb +152 -0
- data/lib/active_model/serializer/null.rb +19 -0
- data/lib/active_model/serializer/reflection.rb +212 -0
- data/lib/active_model/serializer/version.rb +7 -0
- data/lib/active_model_serializers.rb +63 -0
- data/lib/active_model_serializers/adapter.rb +100 -0
- data/lib/active_model_serializers/adapter/attributes.rb +15 -0
- data/lib/active_model_serializers/adapter/base.rb +85 -0
- data/lib/active_model_serializers/adapter/json.rb +23 -0
- data/lib/active_model_serializers/adapter/json_api.rb +535 -0
- data/lib/active_model_serializers/adapter/json_api/deserialization.rb +215 -0
- data/lib/active_model_serializers/adapter/json_api/error.rb +98 -0
- data/lib/active_model_serializers/adapter/json_api/jsonapi.rb +51 -0
- data/lib/active_model_serializers/adapter/json_api/link.rb +85 -0
- data/lib/active_model_serializers/adapter/json_api/meta.rb +39 -0
- data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +90 -0
- data/lib/active_model_serializers/adapter/json_api/relationship.rb +106 -0
- data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +68 -0
- data/lib/active_model_serializers/adapter/null.rb +11 -0
- data/lib/active_model_serializers/callbacks.rb +57 -0
- data/lib/active_model_serializers/deprecate.rb +56 -0
- data/lib/active_model_serializers/deserialization.rb +17 -0
- data/lib/active_model_serializers/json_pointer.rb +16 -0
- data/lib/active_model_serializers/logging.rb +124 -0
- data/lib/active_model_serializers/lookup_chain.rb +82 -0
- data/lib/active_model_serializers/model.rb +132 -0
- data/lib/active_model_serializers/railtie.rb +52 -0
- data/lib/active_model_serializers/register_jsonapi_renderer.rb +80 -0
- data/lib/active_model_serializers/serializable_resource.rb +84 -0
- data/lib/active_model_serializers/serialization_context.rb +41 -0
- data/lib/active_model_serializers/test.rb +9 -0
- data/lib/active_model_serializers/test/schema.rb +140 -0
- data/lib/active_model_serializers/test/serializer.rb +127 -0
- data/lib/generators/rails/USAGE +6 -0
- data/lib/generators/rails/resource_override.rb +12 -0
- data/lib/generators/rails/serializer_generator.rb +38 -0
- data/lib/generators/rails/templates/serializer.rb.erb +8 -0
- data/lib/grape/active_model_serializers.rb +18 -0
- data/lib/grape/formatters/active_model_serializers.rb +34 -0
- data/lib/grape/helpers/active_model_serializers.rb +19 -0
- data/lib/tasks/rubocop.rake +55 -0
- data/test/action_controller/adapter_selector_test.rb +64 -0
- data/test/action_controller/explicit_serializer_test.rb +137 -0
- data/test/action_controller/json/include_test.rb +248 -0
- data/test/action_controller/json_api/deserialization_test.rb +114 -0
- data/test/action_controller/json_api/errors_test.rb +42 -0
- data/test/action_controller/json_api/fields_test.rb +68 -0
- data/test/action_controller/json_api/linked_test.rb +204 -0
- data/test/action_controller/json_api/pagination_test.rb +126 -0
- data/test/action_controller/json_api/transform_test.rb +191 -0
- data/test/action_controller/lookup_proc_test.rb +51 -0
- data/test/action_controller/namespace_lookup_test.rb +239 -0
- data/test/action_controller/serialization_scope_name_test.rb +237 -0
- data/test/action_controller/serialization_test.rb +480 -0
- data/test/active_model_serializers/adapter_for_test.rb +210 -0
- data/test/active_model_serializers/json_pointer_test.rb +24 -0
- data/test/active_model_serializers/logging_test.rb +79 -0
- data/test/active_model_serializers/model_test.rb +144 -0
- data/test/active_model_serializers/railtie_test_isolated.rb +70 -0
- data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +163 -0
- data/test/active_model_serializers/serialization_context_test_isolated.rb +73 -0
- data/test/active_model_serializers/test/schema_test.rb +133 -0
- data/test/active_model_serializers/test/serializer_test.rb +64 -0
- data/test/active_record_test.rb +11 -0
- data/test/adapter/attributes_test.rb +42 -0
- data/test/adapter/deprecation_test.rb +102 -0
- data/test/adapter/json/belongs_to_test.rb +47 -0
- data/test/adapter/json/collection_test.rb +106 -0
- data/test/adapter/json/has_many_test.rb +55 -0
- data/test/adapter/json/transform_test.rb +95 -0
- data/test/adapter/json_api/belongs_to_test.rb +157 -0
- data/test/adapter/json_api/collection_test.rb +98 -0
- data/test/adapter/json_api/errors_test.rb +78 -0
- data/test/adapter/json_api/fields_test.rb +98 -0
- data/test/adapter/json_api/has_many_explicit_serializer_test.rb +98 -0
- data/test/adapter/json_api/has_many_test.rb +175 -0
- data/test/adapter/json_api/has_one_test.rb +82 -0
- data/test/adapter/json_api/include_data_if_sideloaded_test.rb +215 -0
- data/test/adapter/json_api/json_api_test.rb +35 -0
- data/test/adapter/json_api/linked_test.rb +415 -0
- data/test/adapter/json_api/links_test.rb +112 -0
- data/test/adapter/json_api/pagination_links_test.rb +208 -0
- data/test/adapter/json_api/parse_test.rb +139 -0
- data/test/adapter/json_api/relationship_test.rb +399 -0
- data/test/adapter/json_api/resource_meta_test.rb +102 -0
- data/test/adapter/json_api/toplevel_jsonapi_test.rb +84 -0
- data/test/adapter/json_api/transform_test.rb +514 -0
- data/test/adapter/json_api/type_test.rb +195 -0
- data/test/adapter/json_test.rb +48 -0
- data/test/adapter/null_test.rb +24 -0
- data/test/adapter/polymorphic_test.rb +220 -0
- data/test/adapter_test.rb +69 -0
- data/test/array_serializer_test.rb +24 -0
- data/test/benchmark/app.rb +67 -0
- data/test/benchmark/benchmarking_support.rb +69 -0
- data/test/benchmark/bm_active_record.rb +83 -0
- data/test/benchmark/bm_adapter.rb +40 -0
- data/test/benchmark/bm_caching.rb +121 -0
- data/test/benchmark/bm_lookup_chain.rb +85 -0
- data/test/benchmark/bm_transform.rb +47 -0
- data/test/benchmark/config.ru +3 -0
- data/test/benchmark/controllers.rb +85 -0
- data/test/benchmark/fixtures.rb +221 -0
- data/test/cache_test.rb +717 -0
- data/test/collection_serializer_test.rb +129 -0
- data/test/fixtures/active_record.rb +115 -0
- data/test/fixtures/poro.rb +227 -0
- data/test/generators/scaffold_controller_generator_test.rb +26 -0
- data/test/generators/serializer_generator_test.rb +77 -0
- data/test/grape_test.rb +198 -0
- data/test/lint_test.rb +51 -0
- data/test/logger_test.rb +22 -0
- data/test/poro_test.rb +11 -0
- data/test/serializable_resource_test.rb +81 -0
- data/test/serializers/association_macros_test.rb +39 -0
- data/test/serializers/associations_test.rb +520 -0
- data/test/serializers/attribute_test.rb +155 -0
- data/test/serializers/attributes_test.rb +54 -0
- data/test/serializers/caching_configuration_test_isolated.rb +172 -0
- data/test/serializers/configuration_test.rb +34 -0
- data/test/serializers/fieldset_test.rb +16 -0
- data/test/serializers/meta_test.rb +204 -0
- data/test/serializers/options_test.rb +34 -0
- data/test/serializers/read_attribute_for_serialization_test.rb +81 -0
- data/test/serializers/reflection_test.rb +481 -0
- data/test/serializers/root_test.rb +23 -0
- data/test/serializers/serialization_test.rb +57 -0
- data/test/serializers/serializer_for_test.rb +138 -0
- data/test/serializers/serializer_for_with_namespace_test.rb +90 -0
- data/test/support/custom_schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
- data/test/support/isolated_unit.rb +86 -0
- data/test/support/rails5_shims.rb +55 -0
- data/test/support/rails_app.rb +40 -0
- data/test/support/schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
- data/test/support/schemas/active_model_serializers/test/schema_test/my/show.json +6 -0
- data/test/support/schemas/custom/show.json +7 -0
- data/test/support/schemas/hyper_schema.json +93 -0
- data/test/support/schemas/render_using_json_api.json +43 -0
- data/test/support/schemas/simple_json_pointers.json +10 -0
- data/test/support/serialization_testing.rb +81 -0
- data/test/test_helper.rb +72 -0
- metadata +622 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# To add Grape support, require 'grape/active_model_serializers' in the base of your Grape endpoints
|
|
4
|
+
# Then add 'include Grape::ActiveModelSerializers' to enable the formatter and helpers
|
|
5
|
+
require 'active_model_serializers'
|
|
6
|
+
require 'grape/formatters/active_model_serializers'
|
|
7
|
+
require 'grape/helpers/active_model_serializers'
|
|
8
|
+
|
|
9
|
+
module Grape
|
|
10
|
+
module ActiveModelSerializers
|
|
11
|
+
extend ActiveSupport::Concern
|
|
12
|
+
|
|
13
|
+
included do
|
|
14
|
+
formatter :json, Grape::Formatters::ActiveModelSerializers
|
|
15
|
+
helpers Grape::Helpers::ActiveModelSerializers
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# A Grape response formatter that can be used as 'formatter :json, Grape::Formatters::ActiveModelSerializers'
|
|
4
|
+
#
|
|
5
|
+
# Serializer options can be passed as a hash from your Grape endpoint using env[:active_model_serializer_options],
|
|
6
|
+
# or better yet user the render helper in Grape::Helpers::ActiveModelSerializers
|
|
7
|
+
|
|
8
|
+
require 'active_model_serializers/serialization_context'
|
|
9
|
+
|
|
10
|
+
module Grape
|
|
11
|
+
module Formatters
|
|
12
|
+
module ActiveModelSerializers
|
|
13
|
+
def self.call(resource, env)
|
|
14
|
+
serializer_options = build_serializer_options(env)
|
|
15
|
+
::ActiveModelSerializers::SerializableResource.new(resource, serializer_options).to_json
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.build_serializer_options(env)
|
|
19
|
+
ams_options = env[:active_model_serializer_options] || {}
|
|
20
|
+
|
|
21
|
+
# Add serialization context
|
|
22
|
+
ams_options.fetch(:serialization_context) do
|
|
23
|
+
request = env['grape.request']
|
|
24
|
+
ams_options[:serialization_context] = ::ActiveModelSerializers::SerializationContext.new(
|
|
25
|
+
request_url: request.url[/\A[^?]+/],
|
|
26
|
+
query_parameters: request.params
|
|
27
|
+
)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
ams_options
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Helpers can be included in your Grape endpoint as: helpers Grape::Helpers::ActiveModelSerializers
|
|
4
|
+
|
|
5
|
+
module Grape
|
|
6
|
+
module Helpers
|
|
7
|
+
module ActiveModelSerializers
|
|
8
|
+
# A convenience method for passing ActiveModelSerializers serializer options
|
|
9
|
+
#
|
|
10
|
+
# Example: To include relationships in the response: render(post, include: ['comments'])
|
|
11
|
+
#
|
|
12
|
+
# Example: To include pagination meta data: render(posts, meta: { page: posts.page, total_pages: posts.total_pages })
|
|
13
|
+
def render(resource, active_model_serializer_options = {})
|
|
14
|
+
env[:active_model_serializer_options] = active_model_serializer_options
|
|
15
|
+
resource
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
begin
|
|
4
|
+
require 'rubocop'
|
|
5
|
+
require 'rubocop/rake_task'
|
|
6
|
+
rescue LoadError # rubocop:disable Lint/HandleExceptions
|
|
7
|
+
else
|
|
8
|
+
require 'rbconfig'
|
|
9
|
+
# https://github.com/bundler/bundler/blob/1b3eb2465a/lib/bundler/constants.rb#L2
|
|
10
|
+
windows_platforms = /(msdos|mswin|djgpp|mingw)/
|
|
11
|
+
if RbConfig::CONFIG['host_os'] =~ windows_platforms
|
|
12
|
+
desc 'No-op rubocop on Windows-- unsupported platform'
|
|
13
|
+
task :rubocop do
|
|
14
|
+
puts 'Skipping rubocop on Windows'
|
|
15
|
+
end
|
|
16
|
+
elsif defined?(::Rubinius)
|
|
17
|
+
desc 'No-op rubocop to avoid rbx segfault'
|
|
18
|
+
task :rubocop do
|
|
19
|
+
puts 'Skipping rubocop on rbx due to segfault'
|
|
20
|
+
puts 'https://github.com/rubinius/rubinius/issues/3499'
|
|
21
|
+
end
|
|
22
|
+
else
|
|
23
|
+
Rake::Task[:rubocop].clear if Rake::Task.task_defined?(:rubocop)
|
|
24
|
+
patterns = [
|
|
25
|
+
'Gemfile',
|
|
26
|
+
'Rakefile',
|
|
27
|
+
'lib/**/*.{rb,rake}',
|
|
28
|
+
'config/**/*.rb',
|
|
29
|
+
'app/**/*.rb',
|
|
30
|
+
'test/**/*.rb'
|
|
31
|
+
]
|
|
32
|
+
desc 'Execute rubocop'
|
|
33
|
+
RuboCop::RakeTask.new(:rubocop) do |task|
|
|
34
|
+
task.options = ['--rails', '--display-cop-names', '--display-style-guide']
|
|
35
|
+
task.formatters = ['progress']
|
|
36
|
+
task.patterns = patterns
|
|
37
|
+
task.fail_on_error = true
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
namespace :rubocop do
|
|
41
|
+
desc 'Auto-gen rubocop config'
|
|
42
|
+
task :auto_gen_config do
|
|
43
|
+
options = ['--auto-gen-config'].concat patterns
|
|
44
|
+
require 'benchmark'
|
|
45
|
+
result = 0
|
|
46
|
+
cli = RuboCop::CLI.new
|
|
47
|
+
time = Benchmark.realtime do
|
|
48
|
+
result = cli.run(options)
|
|
49
|
+
end
|
|
50
|
+
puts "Finished in #{time} seconds" if cli.options[:debug]
|
|
51
|
+
abort('RuboCop failed!') if result.nonzero?
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'test_helper'
|
|
4
|
+
|
|
5
|
+
module ActionController
|
|
6
|
+
module Serialization
|
|
7
|
+
class AdapterSelectorTest < ActionController::TestCase
|
|
8
|
+
class Profile < Model
|
|
9
|
+
attributes :id, :name, :description
|
|
10
|
+
associations :comments
|
|
11
|
+
end
|
|
12
|
+
class ProfileSerializer < ActiveModel::Serializer
|
|
13
|
+
type 'profiles'
|
|
14
|
+
attributes :name, :description
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class AdapterSelectorTestController < ActionController::Base
|
|
18
|
+
def render_using_default_adapter
|
|
19
|
+
@profile = Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1')
|
|
20
|
+
render json: @profile
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def render_using_adapter_override
|
|
24
|
+
@profile = Profile.new(id: 'render_using_adapter_override', name: 'Name 1', description: 'Description 1', comments: 'Comments 1')
|
|
25
|
+
render json: @profile, adapter: :json_api
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def render_skipping_adapter
|
|
29
|
+
@profile = Profile.new(id: 'render_skipping_adapter_id', name: 'Name 1', description: 'Description 1', comments: 'Comments 1')
|
|
30
|
+
render json: @profile, adapter: false
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
tests AdapterSelectorTestController
|
|
35
|
+
|
|
36
|
+
def test_render_using_default_adapter
|
|
37
|
+
get :render_using_default_adapter
|
|
38
|
+
assert_equal '{"name":"Name 1","description":"Description 1"}', response.body
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def test_render_using_adapter_override
|
|
42
|
+
get :render_using_adapter_override
|
|
43
|
+
|
|
44
|
+
expected = {
|
|
45
|
+
data: {
|
|
46
|
+
id: 'render_using_adapter_override',
|
|
47
|
+
type: 'profiles',
|
|
48
|
+
attributes: {
|
|
49
|
+
name: 'Name 1',
|
|
50
|
+
description: 'Description 1'
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
assert_equal expected.to_json, response.body
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def test_render_skipping_adapter
|
|
59
|
+
get :render_skipping_adapter
|
|
60
|
+
assert_equal '{"id":"render_skipping_adapter_id","name":"Name 1","description":"Description 1"}', response.body
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'test_helper'
|
|
4
|
+
|
|
5
|
+
module ActionController
|
|
6
|
+
module Serialization
|
|
7
|
+
class ExplicitSerializerTest < ActionController::TestCase
|
|
8
|
+
class ExplicitSerializerTestController < ActionController::Base
|
|
9
|
+
def render_using_explicit_serializer
|
|
10
|
+
@profile = Profile.new(name: 'Name 1',
|
|
11
|
+
description: 'Description 1',
|
|
12
|
+
comments: 'Comments 1')
|
|
13
|
+
render json: @profile, serializer: ProfilePreviewSerializer
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def render_array_using_explicit_serializer
|
|
17
|
+
array = [
|
|
18
|
+
Profile.new(name: 'Name 1',
|
|
19
|
+
description: 'Description 1',
|
|
20
|
+
comments: 'Comments 1'),
|
|
21
|
+
Profile.new(name: 'Name 2',
|
|
22
|
+
description: 'Description 2',
|
|
23
|
+
comments: 'Comments 2')
|
|
24
|
+
]
|
|
25
|
+
render json: array,
|
|
26
|
+
serializer: PaginatedSerializer,
|
|
27
|
+
each_serializer: ProfilePreviewSerializer
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def render_array_using_implicit_serializer
|
|
31
|
+
array = [
|
|
32
|
+
Profile.new(name: 'Name 1',
|
|
33
|
+
description: 'Description 1',
|
|
34
|
+
comments: 'Comments 1'),
|
|
35
|
+
Profile.new(name: 'Name 2',
|
|
36
|
+
description: 'Description 2',
|
|
37
|
+
comments: 'Comments 2')
|
|
38
|
+
]
|
|
39
|
+
render json: array,
|
|
40
|
+
each_serializer: ProfilePreviewSerializer
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def render_array_using_explicit_serializer_and_custom_serializers
|
|
44
|
+
@post = Post.new(title: 'New Post', body: 'Body')
|
|
45
|
+
@author = Author.new(name: 'Jane Blogger')
|
|
46
|
+
@author.posts = [@post]
|
|
47
|
+
@post.author = @author
|
|
48
|
+
@first_comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
|
|
49
|
+
@second_comment = Comment.new(id: 2, body: 'ZOMG ANOTHER COMMENT')
|
|
50
|
+
@post.comments = [@first_comment, @second_comment]
|
|
51
|
+
@first_comment.post = @post
|
|
52
|
+
@first_comment.author = nil
|
|
53
|
+
@second_comment.post = @post
|
|
54
|
+
@second_comment.author = nil
|
|
55
|
+
@blog = Blog.new(id: 23, name: 'AMS Blog')
|
|
56
|
+
@post.blog = @blog
|
|
57
|
+
|
|
58
|
+
render json: [@post], each_serializer: PostPreviewSerializer
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def render_using_explicit_each_serializer
|
|
62
|
+
location = Location.new(id: 42, lat: '-23.550520', lng: '-46.633309')
|
|
63
|
+
place = Place.new(id: 1337, name: 'Amazing Place', locations: [location])
|
|
64
|
+
|
|
65
|
+
render json: place, each_serializer: PlaceSerializer
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
tests ExplicitSerializerTestController
|
|
70
|
+
|
|
71
|
+
def test_render_using_explicit_serializer
|
|
72
|
+
get :render_using_explicit_serializer
|
|
73
|
+
|
|
74
|
+
assert_equal 'application/json', @response.content_type
|
|
75
|
+
assert_equal '{"name":"Name 1"}', @response.body
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def test_render_array_using_explicit_serializer
|
|
79
|
+
get :render_array_using_explicit_serializer
|
|
80
|
+
assert_equal 'application/json', @response.content_type
|
|
81
|
+
|
|
82
|
+
expected = [
|
|
83
|
+
{ 'name' => 'Name 1' },
|
|
84
|
+
{ 'name' => 'Name 2' }
|
|
85
|
+
]
|
|
86
|
+
|
|
87
|
+
assert_equal expected.to_json, @response.body
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def test_render_array_using_implicit_serializer
|
|
91
|
+
get :render_array_using_implicit_serializer
|
|
92
|
+
assert_equal 'application/json', @response.content_type
|
|
93
|
+
|
|
94
|
+
expected = [
|
|
95
|
+
{ 'name' => 'Name 1' },
|
|
96
|
+
{ 'name' => 'Name 2' }
|
|
97
|
+
]
|
|
98
|
+
assert_equal expected.to_json, @response.body
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def test_render_array_using_explicit_serializer_and_custom_serializers
|
|
102
|
+
get :render_array_using_explicit_serializer_and_custom_serializers
|
|
103
|
+
|
|
104
|
+
expected = [
|
|
105
|
+
{
|
|
106
|
+
'title' => 'New Post',
|
|
107
|
+
'body' => 'Body',
|
|
108
|
+
'id' => @controller.instance_variable_get(:@post).id,
|
|
109
|
+
'comments' => [{ 'id' => 1 }, { 'id' => 2 }],
|
|
110
|
+
'author' => { 'id' => @controller.instance_variable_get(:@author).id }
|
|
111
|
+
}
|
|
112
|
+
]
|
|
113
|
+
|
|
114
|
+
assert_equal expected.to_json, @response.body
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def test_render_using_explicit_each_serializer
|
|
118
|
+
get :render_using_explicit_each_serializer
|
|
119
|
+
|
|
120
|
+
expected = {
|
|
121
|
+
id: 1337,
|
|
122
|
+
name: 'Amazing Place',
|
|
123
|
+
locations: [
|
|
124
|
+
{
|
|
125
|
+
id: 42,
|
|
126
|
+
lat: '-23.550520',
|
|
127
|
+
lng: '-46.633309',
|
|
128
|
+
address: 'Nowhere' # is a virtual attribute on LocationSerializer
|
|
129
|
+
}
|
|
130
|
+
]
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
assert_equal expected.to_json, response.body
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'test_helper'
|
|
4
|
+
|
|
5
|
+
module ActionController
|
|
6
|
+
module Serialization
|
|
7
|
+
class Json
|
|
8
|
+
class IncludeTest < ActionController::TestCase
|
|
9
|
+
INCLUDE_STRING = 'posts.comments'.freeze
|
|
10
|
+
INCLUDE_HASH = { posts: :comments }.freeze
|
|
11
|
+
DEEP_INCLUDE = 'posts.comments.author'.freeze
|
|
12
|
+
|
|
13
|
+
class IncludeTestController < ActionController::Base
|
|
14
|
+
def setup_data
|
|
15
|
+
ActionController::Base.cache_store.clear
|
|
16
|
+
|
|
17
|
+
@author = Author.new(id: 1, name: 'Steve K.')
|
|
18
|
+
|
|
19
|
+
@post = Post.new(id: 42, title: 'New Post', body: 'Body')
|
|
20
|
+
@first_comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
|
|
21
|
+
@second_comment = Comment.new(id: 2, body: 'ZOMG ANOTHER COMMENT')
|
|
22
|
+
|
|
23
|
+
@post.comments = [@first_comment, @second_comment]
|
|
24
|
+
@post.author = @author
|
|
25
|
+
|
|
26
|
+
@first_comment.post = @post
|
|
27
|
+
@second_comment.post = @post
|
|
28
|
+
|
|
29
|
+
@blog = Blog.new(id: 1, name: 'My Blog!!')
|
|
30
|
+
@post.blog = @blog
|
|
31
|
+
@author.posts = [@post]
|
|
32
|
+
|
|
33
|
+
@first_comment.author = @author
|
|
34
|
+
@second_comment.author = @author
|
|
35
|
+
@author.comments = [@first_comment, @second_comment]
|
|
36
|
+
@author.roles = []
|
|
37
|
+
@author.bio = {}
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def render_without_include
|
|
41
|
+
setup_data
|
|
42
|
+
render json: @author, adapter: :json
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def render_resource_with_include_hash
|
|
46
|
+
setup_data
|
|
47
|
+
render json: @author, include: INCLUDE_HASH, adapter: :json
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def render_resource_with_include_string
|
|
51
|
+
setup_data
|
|
52
|
+
render json: @author, include: INCLUDE_STRING, adapter: :json
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def render_resource_with_deep_include
|
|
56
|
+
setup_data
|
|
57
|
+
render json: @author, include: DEEP_INCLUDE, adapter: :json
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def render_without_recursive_relationships
|
|
61
|
+
# testing recursive includes ('**') can't have any cycles in the
|
|
62
|
+
# relationships, or we enter an infinite loop.
|
|
63
|
+
author = Author.new(id: 11, name: 'Jane Doe')
|
|
64
|
+
post = Post.new(id: 12, title: 'Hello World', body: 'My first post')
|
|
65
|
+
comment = Comment.new(id: 13, body: 'Commentary')
|
|
66
|
+
author.posts = [post]
|
|
67
|
+
post.comments = [comment]
|
|
68
|
+
render json: author
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
tests IncludeTestController
|
|
73
|
+
|
|
74
|
+
def test_render_without_include
|
|
75
|
+
get :render_without_include
|
|
76
|
+
response = JSON.parse(@response.body)
|
|
77
|
+
expected = {
|
|
78
|
+
'author' => {
|
|
79
|
+
'id' => 1,
|
|
80
|
+
'name' => 'Steve K.',
|
|
81
|
+
'posts' => [
|
|
82
|
+
{
|
|
83
|
+
'id' => 42, 'title' => 'New Post', 'body' => 'Body'
|
|
84
|
+
}
|
|
85
|
+
],
|
|
86
|
+
'roles' => [],
|
|
87
|
+
'bio' => {}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
assert_equal(expected, response)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def test_render_resource_with_include_hash
|
|
95
|
+
get :render_resource_with_include_hash
|
|
96
|
+
response = JSON.parse(@response.body)
|
|
97
|
+
|
|
98
|
+
assert_equal(expected_include_response, response)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def test_render_resource_with_include_string
|
|
102
|
+
get :render_resource_with_include_string
|
|
103
|
+
|
|
104
|
+
response = JSON.parse(@response.body)
|
|
105
|
+
|
|
106
|
+
assert_equal(expected_include_response, response)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def test_render_resource_with_deep_include
|
|
110
|
+
get :render_resource_with_deep_include
|
|
111
|
+
|
|
112
|
+
response = JSON.parse(@response.body)
|
|
113
|
+
|
|
114
|
+
assert_equal(expected_deep_include_response, response)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def test_render_with_empty_default_includes
|
|
118
|
+
with_default_includes '' do
|
|
119
|
+
get :render_without_include
|
|
120
|
+
response = JSON.parse(@response.body)
|
|
121
|
+
expected = {
|
|
122
|
+
'author' => {
|
|
123
|
+
'id' => 1,
|
|
124
|
+
'name' => 'Steve K.'
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
assert_equal(expected, response)
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def test_render_with_recursive_default_includes
|
|
132
|
+
with_default_includes '**' do
|
|
133
|
+
get :render_without_recursive_relationships
|
|
134
|
+
response = JSON.parse(@response.body)
|
|
135
|
+
|
|
136
|
+
expected = {
|
|
137
|
+
'id' => 11,
|
|
138
|
+
'name' => 'Jane Doe',
|
|
139
|
+
'roles' => nil,
|
|
140
|
+
'bio' => nil,
|
|
141
|
+
'posts' => [
|
|
142
|
+
{
|
|
143
|
+
'id' => 12,
|
|
144
|
+
'title' => 'Hello World',
|
|
145
|
+
'body' => 'My first post',
|
|
146
|
+
'comments' => [
|
|
147
|
+
{
|
|
148
|
+
'id' => 13,
|
|
149
|
+
'body' => 'Commentary',
|
|
150
|
+
'post' => nil, # not set to avoid infinite recursion
|
|
151
|
+
'author' => nil, # not set to avoid infinite recursion
|
|
152
|
+
}
|
|
153
|
+
],
|
|
154
|
+
'blog' => {
|
|
155
|
+
'id' => 999,
|
|
156
|
+
'name' => 'Custom blog',
|
|
157
|
+
'writer' => nil,
|
|
158
|
+
'articles' => nil
|
|
159
|
+
},
|
|
160
|
+
'author' => nil # not set to avoid infinite recursion
|
|
161
|
+
}
|
|
162
|
+
]
|
|
163
|
+
}
|
|
164
|
+
assert_equal(expected, response)
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def test_render_with_includes_overrides_default_includes
|
|
169
|
+
with_default_includes '' do
|
|
170
|
+
get :render_resource_with_include_hash
|
|
171
|
+
response = JSON.parse(@response.body)
|
|
172
|
+
|
|
173
|
+
assert_equal(expected_include_response, response)
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
private
|
|
178
|
+
|
|
179
|
+
def expected_include_response
|
|
180
|
+
{
|
|
181
|
+
'author' => {
|
|
182
|
+
'id' => 1,
|
|
183
|
+
'name' => 'Steve K.',
|
|
184
|
+
'posts' => [
|
|
185
|
+
{
|
|
186
|
+
'id' => 42, 'title' => 'New Post', 'body' => 'Body',
|
|
187
|
+
'comments' => [
|
|
188
|
+
{
|
|
189
|
+
'id' => 1, 'body' => 'ZOMG A COMMENT'
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
'id' => 2, 'body' => 'ZOMG ANOTHER COMMENT'
|
|
193
|
+
}
|
|
194
|
+
]
|
|
195
|
+
}
|
|
196
|
+
]
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def expected_deep_include_response
|
|
202
|
+
{
|
|
203
|
+
'author' => {
|
|
204
|
+
'id' => 1,
|
|
205
|
+
'name' => 'Steve K.',
|
|
206
|
+
'posts' => [
|
|
207
|
+
{
|
|
208
|
+
'id' => 42, 'title' => 'New Post', 'body' => 'Body',
|
|
209
|
+
'comments' => [
|
|
210
|
+
{
|
|
211
|
+
'id' => 1, 'body' => 'ZOMG A COMMENT',
|
|
212
|
+
'author' => {
|
|
213
|
+
'id' => 1,
|
|
214
|
+
'name' => 'Steve K.'
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
'id' => 2, 'body' => 'ZOMG ANOTHER COMMENT',
|
|
219
|
+
'author' => {
|
|
220
|
+
'id' => 1,
|
|
221
|
+
'name' => 'Steve K.'
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
]
|
|
225
|
+
}
|
|
226
|
+
]
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def with_default_includes(include_directive)
|
|
232
|
+
original = ActiveModelSerializers.config.default_includes
|
|
233
|
+
ActiveModelSerializers.config.default_includes = include_directive
|
|
234
|
+
clear_include_directive_cache
|
|
235
|
+
yield
|
|
236
|
+
ensure
|
|
237
|
+
ActiveModelSerializers.config.default_includes = original
|
|
238
|
+
clear_include_directive_cache
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def clear_include_directive_cache
|
|
242
|
+
ActiveModelSerializers
|
|
243
|
+
.instance_variable_set(:@default_include_directive, nil)
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
end
|