active_model_serializers 0.8.3 → 0.10.0.rc4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +6 -0
- data/.rubocop.yml +86 -0
- data/.rubocop_todo.yml +240 -0
- data/.simplecov +111 -0
- data/.travis.yml +33 -22
- data/CHANGELOG.md +358 -6
- data/CONTRIBUTING.md +220 -0
- data/Gemfile +46 -1
- data/{MIT-LICENSE.txt → LICENSE.txt} +3 -2
- data/README.md +81 -591
- data/Rakefile +68 -11
- data/active_model_serializers.gemspec +57 -23
- data/appveyor.yml +27 -0
- data/docs/ARCHITECTURE.md +120 -0
- data/docs/DESIGN.textile +8 -0
- data/docs/README.md +35 -0
- data/docs/general/adapters.md +162 -0
- data/docs/general/caching.md +52 -0
- data/docs/general/configuration_options.md +27 -0
- data/docs/general/getting_started.md +98 -0
- data/docs/general/instrumentation.md +40 -0
- data/docs/general/logging.md +14 -0
- data/docs/general/rendering.md +153 -0
- data/docs/general/serializers.md +207 -0
- data/docs/how-open-source-maintained.jpg +0 -0
- data/docs/howto/add_pagination_links.md +121 -0
- data/docs/howto/add_root_key.md +51 -0
- data/docs/howto/outside_controller_use.md +58 -0
- data/docs/howto/test.md +152 -0
- data/docs/integrations/ember-and-json-api.md +112 -0
- data/docs/integrations/grape.md +19 -0
- data/docs/jsonapi/schema/schema.json +366 -0
- data/docs/jsonapi/schema.md +140 -0
- data/lib/action_controller/serialization.rb +41 -37
- data/lib/active_model/serializable_resource.rb +72 -0
- data/lib/active_model/serializer/adapter/attributes.rb +66 -0
- data/lib/active_model/serializer/adapter/base.rb +58 -0
- data/lib/active_model/serializer/adapter/cached_serializer.rb +45 -0
- data/lib/active_model/serializer/adapter/fragment_cache.rb +111 -0
- data/lib/active_model/serializer/adapter/json/fragment_cache.rb +13 -0
- data/lib/active_model/serializer/adapter/json.rb +21 -0
- data/lib/active_model/serializer/adapter/json_api/deserialization.rb +207 -0
- data/lib/active_model/serializer/adapter/json_api/fragment_cache.rb +21 -0
- data/lib/active_model/serializer/adapter/json_api/link.rb +44 -0
- data/lib/active_model/serializer/adapter/json_api/pagination_links.rb +58 -0
- data/lib/active_model/serializer/adapter/json_api.rb +223 -0
- data/lib/active_model/serializer/adapter/null.rb +11 -0
- data/lib/active_model/serializer/adapter.rb +91 -0
- data/lib/active_model/serializer/array_serializer.rb +9 -0
- data/lib/active_model/serializer/association.rb +20 -0
- data/lib/active_model/serializer/associations.rb +87 -220
- data/lib/active_model/serializer/attribute.rb +25 -0
- data/lib/active_model/serializer/attributes.rb +82 -0
- data/lib/active_model/serializer/belongs_to_reflection.rb +10 -0
- data/lib/active_model/serializer/caching.rb +100 -0
- data/lib/active_model/serializer/collection_reflection.rb +7 -0
- data/lib/active_model/serializer/collection_serializer.rb +47 -0
- data/lib/active_model/serializer/configuration.rb +28 -0
- data/lib/active_model/serializer/field.rb +56 -0
- data/lib/active_model/serializer/fieldset.rb +31 -0
- data/lib/active_model/serializer/has_many_reflection.rb +10 -0
- data/lib/active_model/serializer/has_one_reflection.rb +10 -0
- data/lib/active_model/serializer/include_tree.rb +111 -0
- data/lib/active_model/serializer/links.rb +33 -0
- data/lib/active_model/serializer/lint.rb +142 -0
- data/lib/active_model/serializer/reflection.rb +91 -0
- data/lib/active_model/serializer/singular_reflection.rb +7 -0
- data/lib/active_model/serializer/type.rb +25 -0
- data/lib/active_model/{serializers → serializer}/version.rb +1 -1
- data/lib/active_model/serializer.rb +99 -479
- data/lib/active_model_serializers/callbacks.rb +55 -0
- data/lib/active_model_serializers/deserialization.rb +13 -0
- data/lib/active_model_serializers/logging.rb +119 -0
- data/lib/active_model_serializers/model.rb +39 -0
- data/lib/active_model_serializers/railtie.rb +38 -0
- data/lib/active_model_serializers/serialization_context.rb +10 -0
- data/lib/active_model_serializers/test/schema.rb +103 -0
- data/lib/active_model_serializers/test/serializer.rb +125 -0
- data/lib/active_model_serializers/test.rb +7 -0
- data/lib/active_model_serializers.rb +20 -92
- data/lib/generators/rails/USAGE +6 -0
- data/lib/generators/rails/resource_override.rb +10 -0
- data/lib/generators/rails/serializer_generator.rb +36 -0
- data/lib/generators/rails/templates/serializer.rb.erb +8 -0
- data/lib/grape/active_model_serializers.rb +14 -0
- data/lib/grape/formatters/active_model_serializers.rb +15 -0
- data/lib/grape/helpers/active_model_serializers.rb +16 -0
- data/test/action_controller/adapter_selector_test.rb +53 -0
- data/test/action_controller/explicit_serializer_test.rb +134 -0
- data/test/action_controller/json/include_test.rb +167 -0
- data/test/action_controller/json_api/deserialization_test.rb +59 -0
- data/test/action_controller/json_api/linked_test.rb +196 -0
- data/test/action_controller/json_api/pagination_test.rb +116 -0
- data/test/{serialization_scope_name_test.rb → action_controller/serialization_scope_name_test.rb} +11 -15
- data/test/action_controller/serialization_test.rb +435 -0
- data/test/active_model_serializers/logging_test.rb +77 -0
- data/test/active_model_serializers/model_test.rb +9 -0
- data/test/active_model_serializers/railtie_test_isolated.rb +57 -0
- data/test/active_model_serializers/serialization_context_test.rb +18 -0
- data/test/active_model_serializers/test/schema_test.rb +128 -0
- data/test/active_model_serializers/test/serializer_test.rb +63 -0
- data/test/active_record_test.rb +9 -0
- data/test/adapter/fragment_cache_test.rb +38 -0
- data/test/adapter/json/belongs_to_test.rb +47 -0
- data/test/adapter/json/collection_test.rb +92 -0
- data/test/adapter/json/has_many_test.rb +47 -0
- data/test/adapter/json_api/belongs_to_test.rb +157 -0
- data/test/adapter/json_api/collection_test.rb +97 -0
- data/test/adapter/json_api/fields_test.rb +89 -0
- data/test/adapter/json_api/has_many_embed_ids_test.rb +45 -0
- data/test/adapter/json_api/has_many_explicit_serializer_test.rb +98 -0
- data/test/adapter/json_api/has_many_test.rb +145 -0
- data/test/adapter/json_api/has_one_test.rb +81 -0
- data/test/adapter/json_api/json_api_test.rb +37 -0
- data/test/adapter/json_api/linked_test.rb +394 -0
- data/test/adapter/json_api/links_test.rb +68 -0
- data/test/adapter/json_api/pagination_links_test.rb +115 -0
- data/test/adapter/json_api/parse_test.rb +139 -0
- data/test/adapter/json_api/resource_type_config_test.rb +71 -0
- data/test/adapter/json_api/toplevel_jsonapi_test.rb +84 -0
- data/test/adapter/json_test.rb +47 -0
- data/test/adapter/null_test.rb +25 -0
- data/test/adapter_test.rb +42 -0
- data/test/array_serializer_test.rb +36 -73
- data/test/collection_serializer_test.rb +100 -0
- data/test/fixtures/active_record.rb +56 -0
- data/test/fixtures/poro.rb +229 -0
- data/test/generators/scaffold_controller_generator_test.rb +24 -0
- data/test/generators/serializer_generator_test.rb +57 -0
- data/test/grape_test.rb +82 -0
- data/test/include_tree/from_include_args_test.rb +26 -0
- data/test/include_tree/from_string_test.rb +94 -0
- data/test/include_tree/include_args_to_hash_test.rb +64 -0
- data/test/lint_test.rb +40 -0
- data/test/logger_test.rb +18 -0
- data/test/poro_test.rb +9 -0
- data/test/serializable_resource_test.rb +27 -0
- data/test/serializers/adapter_for_test.rb +166 -0
- data/test/serializers/association_macros_test.rb +36 -0
- data/test/serializers/associations_test.rb +267 -0
- data/test/serializers/attribute_test.rb +123 -0
- data/test/serializers/attributes_test.rb +52 -0
- data/test/serializers/cache_test.rb +209 -0
- data/test/serializers/configuration_test.rb +32 -0
- data/test/serializers/fieldset_test.rb +14 -0
- data/test/serializers/meta_test.rb +130 -0
- data/test/serializers/options_test.rb +21 -0
- data/test/serializers/root_test.rb +21 -0
- data/test/serializers/serializer_for_test.rb +134 -0
- data/test/support/custom_schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
- data/test/support/isolated_unit.rb +77 -0
- data/test/support/rails5_shims.rb +29 -0
- data/test/support/rails_app.rb +25 -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 +53 -0
- data/test/support/simplecov.rb +6 -0
- data/test/support/stream_capture.rb +50 -0
- data/test/support/test_case.rb +19 -0
- data/test/test_helper.rb +55 -24
- metadata +358 -42
- data/DESIGN.textile +0 -586
- data/Gemfile.edge +0 -9
- data/bench/perf.rb +0 -43
- data/cruft.md +0 -19
- data/lib/active_model/array_serializer.rb +0 -104
- data/lib/active_record/serializer_override.rb +0 -16
- data/lib/generators/resource_override.rb +0 -13
- data/lib/generators/serializer/USAGE +0 -9
- data/lib/generators/serializer/serializer_generator.rb +0 -42
- data/lib/generators/serializer/templates/serializer.rb +0 -19
- data/test/association_test.rb +0 -592
- data/test/caching_test.rb +0 -96
- data/test/generators_test.rb +0 -85
- data/test/no_serialization_scope_test.rb +0 -34
- data/test/serialization_test.rb +0 -392
- data/test/serializer_support_test.rb +0 -51
- data/test/serializer_test.rb +0 -1465
- data/test/test_fakes.rb +0 -217
data/Rakefile
CHANGED
@@ -1,18 +1,75 @@
|
|
1
|
-
|
2
|
-
require
|
3
|
-
|
1
|
+
begin
|
2
|
+
require 'simplecov'
|
3
|
+
rescue LoadError
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'bundler/gem_tasks'
|
7
|
+
|
8
|
+
begin
|
9
|
+
require 'rubocop'
|
10
|
+
require 'rubocop/rake_task'
|
11
|
+
rescue LoadError
|
12
|
+
else
|
13
|
+
Rake::Task[:rubocop].clear if Rake::Task.task_defined?(:rubocop)
|
14
|
+
require 'rbconfig'
|
15
|
+
# https://github.com/bundler/bundler/blob/1b3eb2465a/lib/bundler/constants.rb#L2
|
16
|
+
windows_platforms = /(msdos|mswin|djgpp|mingw)/
|
17
|
+
if RbConfig::CONFIG['host_os'] =~ windows_platforms
|
18
|
+
desc 'No-op rubocop on Windows-- unsupported platform'
|
19
|
+
task :rubocop do
|
20
|
+
puts 'Skipping rubocop on Windows'
|
21
|
+
end
|
22
|
+
elsif defined?(::Rubinius)
|
23
|
+
desc 'No-op rubocop to avoid rbx segfault'
|
24
|
+
task :rubocop do
|
25
|
+
puts 'Skipping rubocop on rbx due to segfault'
|
26
|
+
puts 'https://github.com/rubinius/rubinius/issues/3499'
|
27
|
+
end
|
28
|
+
else
|
29
|
+
Rake::Task[:rubocop].clear if Rake::Task.task_defined?(:rubocop)
|
30
|
+
desc 'Execute rubocop'
|
31
|
+
RuboCop::RakeTask.new(:rubocop) do |task|
|
32
|
+
task.options = ['--rails', '--display-cop-names', '--display-style-guide']
|
33
|
+
task.fail_on_error = true
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
4
37
|
|
5
|
-
|
6
|
-
|
7
|
-
|
38
|
+
require 'rake/testtask'
|
39
|
+
|
40
|
+
Rake::TestTask.new do |t|
|
8
41
|
t.libs << 'test'
|
9
|
-
t.
|
42
|
+
t.test_files = FileList['test/**/*_test.rb']
|
43
|
+
t.ruby_opts = ['-r./test/test_helper.rb']
|
10
44
|
t.verbose = true
|
11
45
|
end
|
12
46
|
|
13
|
-
desc '
|
14
|
-
task :
|
15
|
-
|
47
|
+
desc 'Run isolated tests'
|
48
|
+
task isolated: ['test:isolated:railtie']
|
49
|
+
namespace :test do
|
50
|
+
namespace :isolated do
|
51
|
+
desc 'Run isolated tests for Railtie'
|
52
|
+
task :railtie do
|
53
|
+
dir = File.dirname(__FILE__)
|
54
|
+
file = "#{dir}/test/active_model_serializers/railtie_test_isolated.rb"
|
55
|
+
|
56
|
+
# https://github.com/rails/rails/blob/3d590add45/railties/lib/rails/generators/app_base.rb#L345-L363
|
57
|
+
_bundle_command = Gem.bin_path('bundler', 'bundle')
|
58
|
+
require 'bundler'
|
59
|
+
Bundler.with_clean_env do
|
60
|
+
command = "-w -I#{dir}/lib -I#{dir}/test #{file}"
|
61
|
+
full_command = %("#{Gem.ruby}" #{command})
|
62
|
+
system(full_command) or fail 'Failures' # rubocop:disable Style/AndOr
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
if ENV['RAILS_VERSION'].to_s > '4.0' && RUBY_ENGINE == 'ruby'
|
69
|
+
task default: [:isolated, :test, :rubocop]
|
70
|
+
else
|
71
|
+
task default: [:test, :rubocop]
|
16
72
|
end
|
17
73
|
|
18
|
-
|
74
|
+
desc 'CI test task'
|
75
|
+
task :ci => [:default]
|
@@ -1,24 +1,58 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
4
|
-
require
|
5
|
-
|
6
|
-
Gem::Specification.new do |
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'active_model/serializer/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'active_model_serializers'
|
8
|
+
spec.version = ActiveModel::Serializer::VERSION
|
9
|
+
spec.platform = Gem::Platform::RUBY
|
10
|
+
spec.authors = ['Steve Klabnik']
|
11
|
+
spec.email = ['steve@steveklabnik.com']
|
12
|
+
spec.summary = 'Conventions-based JSON generation for Rails.'
|
13
|
+
spec.description = 'ActiveModel::Serializers allows you to generate your JSON in an object-oriented and convention-driven manner.'
|
14
|
+
spec.homepage = 'https://github.com/rails-api/active_model_serializers'
|
15
|
+
spec.license = 'MIT'
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0")
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.required_ruby_version = '>= 2.0.0'
|
22
|
+
|
23
|
+
rails_versions = '>= 4.0'
|
24
|
+
spec.add_runtime_dependency 'activemodel', rails_versions
|
25
|
+
# 'activesupport', rails_versions
|
26
|
+
# 'builder'
|
27
|
+
|
28
|
+
spec.add_runtime_dependency 'actionpack', rails_versions
|
29
|
+
# 'activesupport', rails_versions
|
30
|
+
# 'rack'
|
31
|
+
# 'rack-test', '~> 0.6.2'
|
32
|
+
|
33
|
+
spec.add_runtime_dependency 'railties', rails_versions
|
34
|
+
# 'activesupport', rails_versions
|
35
|
+
# 'actionpack', rails_versions
|
36
|
+
# 'rake', '>= 0.8.7'
|
37
|
+
|
38
|
+
# 'activesupport', rails_versions
|
39
|
+
# 'i18n,
|
40
|
+
# 'tzinfo'
|
41
|
+
# 'minitest'
|
42
|
+
# 'thread_safe'
|
43
|
+
|
44
|
+
spec.add_development_dependency 'activerecord', rails_versions
|
45
|
+
# arel
|
46
|
+
# activesupport
|
47
|
+
# activemodel
|
48
|
+
|
49
|
+
# Soft dependency for pagination
|
50
|
+
spec.add_development_dependency 'kaminari', ' ~> 0.16.3'
|
51
|
+
spec.add_development_dependency 'will_paginate', '~> 3.0', '>= 3.0.7'
|
52
|
+
|
53
|
+
spec.add_development_dependency 'bundler', '~> 1.6'
|
54
|
+
spec.add_development_dependency 'timecop', '~> 0.7'
|
55
|
+
spec.add_development_dependency 'minitest-reporters'
|
56
|
+
spec.add_development_dependency 'grape', ['>= 0.13', '< 1.0']
|
57
|
+
spec.add_development_dependency 'json_schema'
|
24
58
|
end
|
data/appveyor.yml
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
version: '{build}'
|
2
|
+
|
3
|
+
skip_tags: true
|
4
|
+
|
5
|
+
environment:
|
6
|
+
matrix:
|
7
|
+
- ruby_version: "200"
|
8
|
+
- ruby_version: "200-x64"
|
9
|
+
- ruby_version: "21"
|
10
|
+
- ruby_version: "21-x64"
|
11
|
+
|
12
|
+
cache:
|
13
|
+
- vendor/bundle
|
14
|
+
|
15
|
+
install:
|
16
|
+
- SET PATH=C:\Ruby%ruby_version%\bin;%PATH%
|
17
|
+
- ruby --version
|
18
|
+
- gem --version
|
19
|
+
- gem install bundler
|
20
|
+
- bundler --version
|
21
|
+
- bundle platform
|
22
|
+
- bundle install --path=vendor/bundle --retry=3 --jobs=3
|
23
|
+
|
24
|
+
test_script:
|
25
|
+
- bundle exec rake ci
|
26
|
+
|
27
|
+
build: off
|
@@ -0,0 +1,120 @@
|
|
1
|
+
[Back to Guides](README.md)
|
2
|
+
|
3
|
+
# ARCHITECTURE
|
4
|
+
|
5
|
+
An **`ActiveModel::Serializer`** wraps a [serializable resource](https://github.com/rails/rails/blob/4-2-stable/activemodel/lib/active_model/serialization.rb)
|
6
|
+
and exposes an `attributes` method, among a few others.
|
7
|
+
It allows you to specify which attributes and associations should be represented in the serializatation of the resource.
|
8
|
+
It requires an adapter to transform its attributes into a JSON document; it cannot be serialized itself.
|
9
|
+
It may be useful to think of it as a
|
10
|
+
[presenter](http://blog.steveklabnik.com/posts/2011-09-09-better-ruby-presenters).
|
11
|
+
|
12
|
+
The **`ActiveModel::ArraySerializer`** represent a collection of resources as serializers
|
13
|
+
and, if there is no serializer, primitives.
|
14
|
+
|
15
|
+
The **`ActiveModel::Adapter`** describes the structure of the JSON document generated from a
|
16
|
+
serializer. For example, the `Attributes` example represents each serializer as its
|
17
|
+
unmodified attributes. The `JsonApi` adapter represents the serializer as a [JSON
|
18
|
+
API](http://jsonapi.org/) document.
|
19
|
+
|
20
|
+
The **`ActiveModel::SerializableResource`** acts to coordinate the serializer(s) and adapter
|
21
|
+
to an object that responds to `to_json`, and `as_json`. It is used in the controller to
|
22
|
+
encapsulate the serialization resource when rendered. However, it can also be used on its own
|
23
|
+
to serialize a resource outside of a controller, as well.
|
24
|
+
|
25
|
+
## Primitive handling
|
26
|
+
|
27
|
+
Definitions: A primitive is usually a String or Array. There is no serializer
|
28
|
+
defined for them; they will be serialized when the resource is converted to JSON (`as_json` or
|
29
|
+
`to_json`). (The below also applies for any object with no serializer.)
|
30
|
+
|
31
|
+
ActiveModelSerializers doesn't handle primitives passed to `render json:` at all.
|
32
|
+
|
33
|
+
However, when a primitive value is an attribute or in a collection,
|
34
|
+
it is not modified.
|
35
|
+
|
36
|
+
Internally, if no serializer can be found in the controller, the resource is not decorated by
|
37
|
+
ActiveModelSerializers.
|
38
|
+
|
39
|
+
If the collection serializer (ArraySerializer) cannot
|
40
|
+
identify a serializer for a resource in its collection, it raises [`NoSerializerError`](https://github.com/rails-api/active_model_serializers/issues/1191#issuecomment-142327128)
|
41
|
+
which is rescued in `AcitveModel::Serializer::Reflection#build_association` which sets
|
42
|
+
the association value directly:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
reflection_options[:virtual_value] = association_value.try(:as_json) || association_value
|
46
|
+
```
|
47
|
+
|
48
|
+
(which is called by the adapter as `serializer.associations(*)`.)
|
49
|
+
|
50
|
+
## How options are parsed
|
51
|
+
|
52
|
+
High-level overview:
|
53
|
+
|
54
|
+
- For a collection
|
55
|
+
- `:serializer` specifies the collection serializer and
|
56
|
+
- `:each_serializer` specifies the serializer for each resource in the collection.
|
57
|
+
- For a single resource, the `:serializer` option is the resource serializer.
|
58
|
+
- Options are partitioned in serializer options and adapter options. Keys for adapter options are specified by
|
59
|
+
[`ADAPTER_OPTIONS`](https://github.com/rails-api/active_model_serializers/blob/master/lib/active_model/serializable_resource.rb#L4).
|
60
|
+
The remaining options are serializer options.
|
61
|
+
|
62
|
+
Details:
|
63
|
+
|
64
|
+
1. **ActionController::Serialization**
|
65
|
+
1. `serializable_resource = ActiveModel::SerializableResource.new(resource, options)`
|
66
|
+
1. `options` are partitioned into `adapter_opts` and everything else (`serializer_opts`).
|
67
|
+
The adapter options keys for the are defined by `ADAPTER_OPTIONS`.
|
68
|
+
1. **ActiveModel::SerializableResource**
|
69
|
+
1. `if serializable_resource.serializer?` (there is a serializer for the resource, and an adapter is used.)
|
70
|
+
- Where `serializer?` is `use_adapter? && !!(serializer)`
|
71
|
+
- Where `use_adapter?`: 'True when no explicit adapter given, or explicit value is truthy (non-nil);
|
72
|
+
False when explicit adapter is falsy (nil or false)'
|
73
|
+
- Where `serializer`:
|
74
|
+
1. from explicit `:serializer` option, else
|
75
|
+
2. implicitly from resource `ActiveModel::Serializer.serializer_for(resource)`
|
76
|
+
1. A side-effect of checking `serializer` is:
|
77
|
+
- The `:serializer` option is removed from the serializer_opts hash
|
78
|
+
- If the `:each_serializer` option is present, it is removed from the serializer_opts hash and set as the `:serializer` option
|
79
|
+
1. The serializer and adapter are created as
|
80
|
+
1. `serializer_instance = serializer.new(resource, serializer_opts)`
|
81
|
+
2. `adapter_instance = ActiveModel::Serializer::Adapter.create(serializer_instance, adapter_opts)`
|
82
|
+
1. **ActiveModel::Serializer::ArraySerializer#new**
|
83
|
+
1. If the `serializer_instance` was a `ArraySerializer` and the `:serializer` serializer_opts
|
84
|
+
is present, then [that serializer is passed into each resource](https://github.com/rails-api/active_model_serializers/blob/a54d237e2828fe6bab1ea5dfe6360d4ecc8214cd/lib/active_model/serializer/array_serializer.rb#L14-L16).
|
85
|
+
1. **ActiveModel::Serializer#attributes** is used by the adapter to get the attributes for
|
86
|
+
resource as defined by the serializer.
|
87
|
+
|
88
|
+
## What does a 'serializable resource' look like?
|
89
|
+
|
90
|
+
- An `ActiveRecord::Base` object.
|
91
|
+
- Any Ruby object at passes or otherwise passes the
|
92
|
+
[Lint](http://www.rubydoc.info/github/rails-api/active_model_serializers/ActiveModel/Serializer/Lint/Tests)
|
93
|
+
[code](https://github.com/rails-api/active_model_serializers/blob/master/lib/active_model/serializer/lint.rb).
|
94
|
+
|
95
|
+
ActiveModelSerializers provides a
|
96
|
+
[`ActiveModelSerializers::Model`](https://github.com/rails-api/active_model_serializers/blob/master/lib/active_model_serializers/model.rb),
|
97
|
+
which is a simple serializable PORO (Plain-Old Ruby Object).
|
98
|
+
|
99
|
+
ActiveModelSerializers::Model may be used either as a template, or in production code.
|
100
|
+
|
101
|
+
```ruby
|
102
|
+
class MyModel < ActiveModelSerializers::Model
|
103
|
+
attr_accessor :id, :name, :level
|
104
|
+
end
|
105
|
+
```
|
106
|
+
|
107
|
+
The default serializer for `MyModel` would be `MyModelSerializer` whether MyModel is an
|
108
|
+
ActiveRecord::Base object or not.
|
109
|
+
|
110
|
+
Outside of the controller the rules are **exactly** the same as for records. For example:
|
111
|
+
|
112
|
+
```ruby
|
113
|
+
render json: MyModel.new(level: 'awesome'), adapter: :json
|
114
|
+
```
|
115
|
+
|
116
|
+
would be serialized the same as
|
117
|
+
|
118
|
+
```ruby
|
119
|
+
ActiveModel::SerializableResource.new(MyModel.new(level: 'awesome'), adapter: :json).as_json
|
120
|
+
```
|
data/docs/DESIGN.textile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
<strong>This was the original design document for serializers.</strong> It is useful mostly for historical purposes as the public API has changed.
|
2
|
def initialize(post, scope)
|
1
3
|
@post, @scope = post, scope
|
2
4
|
end
|
3
5
|
def as_json
|
4
6
|
{ post: { title: @post.name, body: @post.body } }
|
5
7
|
end
|
6
8
|
def show
|
7
9
|
@post = Post.find(params[:id])
|
8
10
|
render json: @post
|
9
11
|
end
|
10
12
|
def initialize(post, scope)
|
11
13
|
@post, @scope = post, scope
|
12
14
|
end
|
13
15
|
def serializable_hash
|
14
16
|
{ title: @post.name, body: @post.body }
|
15
17
|
end
|
16
18
|
def as_json
|
17
19
|
{ post: serializable_hash }
|
18
20
|
end
|
19
21
|
def initialize(post, scope)
|
20
22
|
@post, @scope = post, scope
|
21
23
|
end
|
22
24
|
def as_json
|
23
25
|
{ post: serializable_hash }
|
24
26
|
end
|
25
27
|
def serializable_hash
|
26
28
|
hash = post
|
27
29
|
hash.merge!(super_data) if super?
|
28
30
|
hash
|
29
31
|
end
|
30
32
|
def post
|
31
33
|
{ title: @post.name, body: @post.body }
|
32
34
|
end
|
33
35
|
def super_data
|
34
36
|
{ email: @post.email }
|
35
37
|
end
|
36
38
|
def super?
|
37
39
|
@scope.superuser?
|
38
40
|
end
|
39
41
|
# For now, we use a very simple authorization structure. These tests will need
|
40
42
|
# refactoring if we change that.
|
41
43
|
plebe = OpenStruct.new(super?: false)
|
42
44
|
god = OpenStruct.new(super?: true)
|
43
45
|
post = OpenStruct.new(title: "Welcome to my blog!", body: "Blah blah blah", email: "tenderlove@gmail.com")
|
44
46
|
test "a regular user sees just the title and body" do
|
45
47
|
json = PostSerializer.new(post, plebe).to_json
|
46
48
|
hash = JSON.parse(json)
|
47
49
|
assert_equal post.title, hash.delete("title")
|
48
50
|
assert_equal post.body, hash.delete("body")
|
49
51
|
assert_empty hash
|
50
52
|
end
|
51
53
|
test "a superuser sees the title, body and email" do
|
52
54
|
json = PostSerializer.new(post, god).to_json
|
53
55
|
hash = JSON.parse(json)
|
54
56
|
assert_equal post.title, hash.delete("title")
|
55
57
|
assert_equal post.body, hash.delete("body")
|
56
58
|
assert_equal post.email, hash.delete("email")
|
57
59
|
assert_empty hash
|
58
60
|
end
|
59
61
|
# @param [~body, ~title, ~email] post the post to serialize
|
60
62
|
# @param [~super] scope the authorization scope for this serializer
|
61
63
|
def initialize(post, scope)
|
62
64
|
@post, @scope = post, scope
|
63
65
|
end
|
64
66
|
# ...
|
67
|
+
ActiveModel::Serializer+ to simplify our post serializer.
|
65
68
|
attributes :title, :body
|
66
69
|
def serializable_hash
|
67
70
|
hash = attributes
|
68
71
|
hash.merge!(super_data) if super?
|
69
72
|
hash
|
70
73
|
end
|
71
74
|
def super_data
|
72
75
|
{ email: @post.email }
|
73
76
|
end
|
74
77
|
def super?
|
75
78
|
@scope.superuser?
|
76
79
|
end
|
80
|
+
attributes+ that extracts those attributes from the post model.
|
77
81
|
attributes :title, :body
|
78
82
|
def attributes
|
79
83
|
hash = super
|
80
84
|
hash.merge!(email: post.email) if super?
|
81
85
|
hash
|
82
86
|
end
|
83
87
|
def super?
|
84
88
|
@scope.superuser?
|
85
89
|
end
|
90
|
+
attributes+. We can call +super+ to get the hash based on the attributes we declared, and then add in any additional
|
86
91
|
attributes :title, :body
|
87
92
|
has_many :comments
|
88
93
|
def attributes
|
89
94
|
hash = super
|
90
95
|
hash.merge!(email: post.email) if super?
|
91
96
|
hash
|
92
97
|
end
|
93
98
|
def super?
|
94
99
|
@scope.superuser?
|
95
100
|
end
|
96
101
|
post: {
|
97
102
|
title: "Hello Blog!",
|
98
103
|
body: "This is my first post. Isn't it fabulous!",
|
99
104
|
comments: [
|
100
105
|
{
|
101
106
|
title: "Awesome",
|
102
107
|
body: "Your first post is great"
|
103
108
|
}
|
104
109
|
]
|
105
110
|
}
|
106
111
|
def initialize(comment, scope)
|
107
112
|
@comment, @scope = comment, scope
|
108
113
|
end
|
109
114
|
def serializable_hash
|
110
115
|
{ title: @comment.title }
|
111
116
|
end
|
112
117
|
def as_json
|
113
118
|
{ comment: serializable_hash }
|
114
119
|
end
|
115
120
|
post: {
|
116
121
|
title: "Hello Blog!",
|
117
122
|
body: "This is my first post. Isn't it fabulous!",
|
118
123
|
comments: [{ title: "Awesome" }]
|
119
124
|
}
|
125
|
+
comments+ accessor on the post object. We can override the +comments+ accessor to limit the comments used
|
120
126
|
attributes :title. :body
|
121
127
|
has_many :comments
|
122
128
|
def attributes
|
123
129
|
hash = super
|
124
130
|
hash.merge!(email: post.email) if super?
|
125
131
|
hash
|
126
132
|
end
|
127
133
|
def comments
|
128
134
|
post.comments_for(scope)
|
129
135
|
end
|
130
136
|
def super?
|
131
137
|
@scope.superuser?
|
132
138
|
end
|
139
|
+
ActiveModel::Serializer+ will still embed the comments, but this time it will use just the comments
|
133
140
|
has_many :followed_posts, :key => :posts
|
134
141
|
has_one :owned_account, :key => :account
|
135
142
|
has_many :followed_posts, :key => :posts, :serializer => CustomPostSerializer
|
136
143
|
has_one :owne_account, :key => :account, :serializer => PrivateAccountSerializer
|
137
144
|
post: {
|
138
145
|
id: 1
|
139
146
|
title: "Hello Blog!",
|
140
147
|
body: "This is my first post. Isn't it fabulous!",
|
141
148
|
comments: [1,2]
|
142
149
|
},
|
143
150
|
comments: [
|
144
151
|
{
|
145
152
|
id: 1
|
146
153
|
title: "Awesome",
|
147
154
|
body: "Your first post is great"
|
148
155
|
},
|
149
156
|
{
|
150
157
|
id: 2
|
151
158
|
title: "Not so awesome",
|
152
159
|
body: "Why is it so short!"
|
153
160
|
}
|
154
161
|
]
|
155
162
|
attributes :id, :title, :body
|
156
163
|
# define any logic for dealing with authorization-based attributes here
|
157
164
|
attributes :title, :body
|
158
165
|
has_many :comments
|
159
166
|
def as_json
|
160
167
|
{ post: serializable_hash }.merge!(associations)
|
161
168
|
end
|
162
169
|
def serializable_hash
|
163
170
|
post_hash = attributes
|
164
171
|
post_hash.merge!(association_ids)
|
165
172
|
post_hash
|
166
173
|
end
|
167
174
|
def attributes
|
168
175
|
hash = super
|
169
176
|
hash.merge!(email: post.email) if super?
|
170
177
|
hash
|
171
178
|
end
|
172
179
|
def comments
|
173
180
|
post.comments_for(scope)
|
174
181
|
end
|
175
182
|
def super?
|
176
183
|
@scope.superuser?
|
177
184
|
end
|
185
|
+
associations+, creates a hash of all of the define associations, using their defined
|
186
|
+
comments+ method.
|
178
187
|
class CommentSerializer < ActiveModel::Serializer
|
179
188
|
attributes :id, :title
|
180
189
|
end
|
181
190
|
# same as before
|
182
191
|
# ...
|
183
192
|
serialization_scope :current_app
|
184
193
|
posts: [
|
185
194
|
{
|
186
195
|
title: "FIRST POST!",
|
187
196
|
body: "It's my first pooooost"
|
188
197
|
},
|
189
198
|
{ title: "Second post!",
|
190
199
|
body: "Zomg I made it to my second post"
|
191
200
|
}
|
192
201
|
]
|
193
202
|
def serializable_array
|
194
203
|
serializers.map do |serializer|
|
195
204
|
serializer.serializable_hash
|
196
205
|
end
|
197
206
|
end
|
198
207
|
def as_json
|
199
208
|
hash = { root => serializable_array }
|
200
209
|
hash.merge!(associations)
|
201
210
|
hash
|
202
211
|
end
|
data/docs/README.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# Docs - ActiveModel::Serializer 0.10.x
|
2
|
+
|
3
|
+
This is the documentation of ActiveModelSerializers, it's focused on the **0.10.x version.**
|
4
|
+
|
5
|
+
-----
|
6
|
+
|
7
|
+
## General
|
8
|
+
|
9
|
+
- [Getting Started](general/getting_started.md)
|
10
|
+
- [Configuration Options](general/configuration_options.md)
|
11
|
+
- [Serializers](general/serializers.md)
|
12
|
+
- [Adapters](general/adapters.md)
|
13
|
+
- [Rendering](general/rendering.md)
|
14
|
+
- [Caching](general/caching.md)
|
15
|
+
- [Logging](general/logging.md)
|
16
|
+
- [Instrumentation](general/instrumentation.md)
|
17
|
+
- [JSON API Schema](jsonapi/schema.md)
|
18
|
+
- [ARCHITECTURE](ARCHITECTURE.md)
|
19
|
+
|
20
|
+
## How to
|
21
|
+
|
22
|
+
- [How to add root key](howto/add_root_key.md)
|
23
|
+
- [How to add pagination links](howto/add_pagination_links.md)
|
24
|
+
- [Using ActiveModelSerializers Outside Of Controllers](howto/outside_controller_use.md)
|
25
|
+
- [Testing ActiveModelSerializers](howto/test.md)
|
26
|
+
|
27
|
+
## Integrations
|
28
|
+
|
29
|
+
| Integration | Supported ActiveModelSerializers versions | Gem name and/or link
|
30
|
+
|----|-----|----
|
31
|
+
| Ember.js | 0.9.x | [active-model-adapter](https://github.com/ember-data/active-model-adapter)
|
32
|
+
| Ember.js | 0.10.x + | [docs/integrations/ember-and-json-api.md](integrations/ember-and-json-api.md)
|
33
|
+
| Grape | 0.10.x + | [docs/integrations/grape.md](integrations/grape.md) |
|
34
|
+
| Grape | 0.9.x | https://github.com/jrhe/grape-active_model_serializers/ |
|
35
|
+
| Sinatra | 0.9.x | https://github.com/SauloSilva/sinatra-active-model-serializers/
|