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.
Files changed (184) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +6 -0
  3. data/.rubocop.yml +86 -0
  4. data/.rubocop_todo.yml +240 -0
  5. data/.simplecov +111 -0
  6. data/.travis.yml +33 -22
  7. data/CHANGELOG.md +358 -6
  8. data/CONTRIBUTING.md +220 -0
  9. data/Gemfile +46 -1
  10. data/{MIT-LICENSE.txt → LICENSE.txt} +3 -2
  11. data/README.md +81 -591
  12. data/Rakefile +68 -11
  13. data/active_model_serializers.gemspec +57 -23
  14. data/appveyor.yml +27 -0
  15. data/docs/ARCHITECTURE.md +120 -0
  16. data/docs/DESIGN.textile +8 -0
  17. data/docs/README.md +35 -0
  18. data/docs/general/adapters.md +162 -0
  19. data/docs/general/caching.md +52 -0
  20. data/docs/general/configuration_options.md +27 -0
  21. data/docs/general/getting_started.md +98 -0
  22. data/docs/general/instrumentation.md +40 -0
  23. data/docs/general/logging.md +14 -0
  24. data/docs/general/rendering.md +153 -0
  25. data/docs/general/serializers.md +207 -0
  26. data/docs/how-open-source-maintained.jpg +0 -0
  27. data/docs/howto/add_pagination_links.md +121 -0
  28. data/docs/howto/add_root_key.md +51 -0
  29. data/docs/howto/outside_controller_use.md +58 -0
  30. data/docs/howto/test.md +152 -0
  31. data/docs/integrations/ember-and-json-api.md +112 -0
  32. data/docs/integrations/grape.md +19 -0
  33. data/docs/jsonapi/schema/schema.json +366 -0
  34. data/docs/jsonapi/schema.md +140 -0
  35. data/lib/action_controller/serialization.rb +41 -37
  36. data/lib/active_model/serializable_resource.rb +72 -0
  37. data/lib/active_model/serializer/adapter/attributes.rb +66 -0
  38. data/lib/active_model/serializer/adapter/base.rb +58 -0
  39. data/lib/active_model/serializer/adapter/cached_serializer.rb +45 -0
  40. data/lib/active_model/serializer/adapter/fragment_cache.rb +111 -0
  41. data/lib/active_model/serializer/adapter/json/fragment_cache.rb +13 -0
  42. data/lib/active_model/serializer/adapter/json.rb +21 -0
  43. data/lib/active_model/serializer/adapter/json_api/deserialization.rb +207 -0
  44. data/lib/active_model/serializer/adapter/json_api/fragment_cache.rb +21 -0
  45. data/lib/active_model/serializer/adapter/json_api/link.rb +44 -0
  46. data/lib/active_model/serializer/adapter/json_api/pagination_links.rb +58 -0
  47. data/lib/active_model/serializer/adapter/json_api.rb +223 -0
  48. data/lib/active_model/serializer/adapter/null.rb +11 -0
  49. data/lib/active_model/serializer/adapter.rb +91 -0
  50. data/lib/active_model/serializer/array_serializer.rb +9 -0
  51. data/lib/active_model/serializer/association.rb +20 -0
  52. data/lib/active_model/serializer/associations.rb +87 -220
  53. data/lib/active_model/serializer/attribute.rb +25 -0
  54. data/lib/active_model/serializer/attributes.rb +82 -0
  55. data/lib/active_model/serializer/belongs_to_reflection.rb +10 -0
  56. data/lib/active_model/serializer/caching.rb +100 -0
  57. data/lib/active_model/serializer/collection_reflection.rb +7 -0
  58. data/lib/active_model/serializer/collection_serializer.rb +47 -0
  59. data/lib/active_model/serializer/configuration.rb +28 -0
  60. data/lib/active_model/serializer/field.rb +56 -0
  61. data/lib/active_model/serializer/fieldset.rb +31 -0
  62. data/lib/active_model/serializer/has_many_reflection.rb +10 -0
  63. data/lib/active_model/serializer/has_one_reflection.rb +10 -0
  64. data/lib/active_model/serializer/include_tree.rb +111 -0
  65. data/lib/active_model/serializer/links.rb +33 -0
  66. data/lib/active_model/serializer/lint.rb +142 -0
  67. data/lib/active_model/serializer/reflection.rb +91 -0
  68. data/lib/active_model/serializer/singular_reflection.rb +7 -0
  69. data/lib/active_model/serializer/type.rb +25 -0
  70. data/lib/active_model/{serializers → serializer}/version.rb +1 -1
  71. data/lib/active_model/serializer.rb +99 -479
  72. data/lib/active_model_serializers/callbacks.rb +55 -0
  73. data/lib/active_model_serializers/deserialization.rb +13 -0
  74. data/lib/active_model_serializers/logging.rb +119 -0
  75. data/lib/active_model_serializers/model.rb +39 -0
  76. data/lib/active_model_serializers/railtie.rb +38 -0
  77. data/lib/active_model_serializers/serialization_context.rb +10 -0
  78. data/lib/active_model_serializers/test/schema.rb +103 -0
  79. data/lib/active_model_serializers/test/serializer.rb +125 -0
  80. data/lib/active_model_serializers/test.rb +7 -0
  81. data/lib/active_model_serializers.rb +20 -92
  82. data/lib/generators/rails/USAGE +6 -0
  83. data/lib/generators/rails/resource_override.rb +10 -0
  84. data/lib/generators/rails/serializer_generator.rb +36 -0
  85. data/lib/generators/rails/templates/serializer.rb.erb +8 -0
  86. data/lib/grape/active_model_serializers.rb +14 -0
  87. data/lib/grape/formatters/active_model_serializers.rb +15 -0
  88. data/lib/grape/helpers/active_model_serializers.rb +16 -0
  89. data/test/action_controller/adapter_selector_test.rb +53 -0
  90. data/test/action_controller/explicit_serializer_test.rb +134 -0
  91. data/test/action_controller/json/include_test.rb +167 -0
  92. data/test/action_controller/json_api/deserialization_test.rb +59 -0
  93. data/test/action_controller/json_api/linked_test.rb +196 -0
  94. data/test/action_controller/json_api/pagination_test.rb +116 -0
  95. data/test/{serialization_scope_name_test.rb → action_controller/serialization_scope_name_test.rb} +11 -15
  96. data/test/action_controller/serialization_test.rb +435 -0
  97. data/test/active_model_serializers/logging_test.rb +77 -0
  98. data/test/active_model_serializers/model_test.rb +9 -0
  99. data/test/active_model_serializers/railtie_test_isolated.rb +57 -0
  100. data/test/active_model_serializers/serialization_context_test.rb +18 -0
  101. data/test/active_model_serializers/test/schema_test.rb +128 -0
  102. data/test/active_model_serializers/test/serializer_test.rb +63 -0
  103. data/test/active_record_test.rb +9 -0
  104. data/test/adapter/fragment_cache_test.rb +38 -0
  105. data/test/adapter/json/belongs_to_test.rb +47 -0
  106. data/test/adapter/json/collection_test.rb +92 -0
  107. data/test/adapter/json/has_many_test.rb +47 -0
  108. data/test/adapter/json_api/belongs_to_test.rb +157 -0
  109. data/test/adapter/json_api/collection_test.rb +97 -0
  110. data/test/adapter/json_api/fields_test.rb +89 -0
  111. data/test/adapter/json_api/has_many_embed_ids_test.rb +45 -0
  112. data/test/adapter/json_api/has_many_explicit_serializer_test.rb +98 -0
  113. data/test/adapter/json_api/has_many_test.rb +145 -0
  114. data/test/adapter/json_api/has_one_test.rb +81 -0
  115. data/test/adapter/json_api/json_api_test.rb +37 -0
  116. data/test/adapter/json_api/linked_test.rb +394 -0
  117. data/test/adapter/json_api/links_test.rb +68 -0
  118. data/test/adapter/json_api/pagination_links_test.rb +115 -0
  119. data/test/adapter/json_api/parse_test.rb +139 -0
  120. data/test/adapter/json_api/resource_type_config_test.rb +71 -0
  121. data/test/adapter/json_api/toplevel_jsonapi_test.rb +84 -0
  122. data/test/adapter/json_test.rb +47 -0
  123. data/test/adapter/null_test.rb +25 -0
  124. data/test/adapter_test.rb +42 -0
  125. data/test/array_serializer_test.rb +36 -73
  126. data/test/collection_serializer_test.rb +100 -0
  127. data/test/fixtures/active_record.rb +56 -0
  128. data/test/fixtures/poro.rb +229 -0
  129. data/test/generators/scaffold_controller_generator_test.rb +24 -0
  130. data/test/generators/serializer_generator_test.rb +57 -0
  131. data/test/grape_test.rb +82 -0
  132. data/test/include_tree/from_include_args_test.rb +26 -0
  133. data/test/include_tree/from_string_test.rb +94 -0
  134. data/test/include_tree/include_args_to_hash_test.rb +64 -0
  135. data/test/lint_test.rb +40 -0
  136. data/test/logger_test.rb +18 -0
  137. data/test/poro_test.rb +9 -0
  138. data/test/serializable_resource_test.rb +27 -0
  139. data/test/serializers/adapter_for_test.rb +166 -0
  140. data/test/serializers/association_macros_test.rb +36 -0
  141. data/test/serializers/associations_test.rb +267 -0
  142. data/test/serializers/attribute_test.rb +123 -0
  143. data/test/serializers/attributes_test.rb +52 -0
  144. data/test/serializers/cache_test.rb +209 -0
  145. data/test/serializers/configuration_test.rb +32 -0
  146. data/test/serializers/fieldset_test.rb +14 -0
  147. data/test/serializers/meta_test.rb +130 -0
  148. data/test/serializers/options_test.rb +21 -0
  149. data/test/serializers/root_test.rb +21 -0
  150. data/test/serializers/serializer_for_test.rb +134 -0
  151. data/test/support/custom_schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
  152. data/test/support/isolated_unit.rb +77 -0
  153. data/test/support/rails5_shims.rb +29 -0
  154. data/test/support/rails_app.rb +25 -0
  155. data/test/support/schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
  156. data/test/support/schemas/active_model_serializers/test/schema_test/my/show.json +6 -0
  157. data/test/support/schemas/custom/show.json +7 -0
  158. data/test/support/schemas/hyper_schema.json +93 -0
  159. data/test/support/schemas/render_using_json_api.json +43 -0
  160. data/test/support/schemas/simple_json_pointers.json +10 -0
  161. data/test/support/serialization_testing.rb +53 -0
  162. data/test/support/simplecov.rb +6 -0
  163. data/test/support/stream_capture.rb +50 -0
  164. data/test/support/test_case.rb +19 -0
  165. data/test/test_helper.rb +55 -24
  166. metadata +358 -42
  167. data/DESIGN.textile +0 -586
  168. data/Gemfile.edge +0 -9
  169. data/bench/perf.rb +0 -43
  170. data/cruft.md +0 -19
  171. data/lib/active_model/array_serializer.rb +0 -104
  172. data/lib/active_record/serializer_override.rb +0 -16
  173. data/lib/generators/resource_override.rb +0 -13
  174. data/lib/generators/serializer/USAGE +0 -9
  175. data/lib/generators/serializer/serializer_generator.rb +0 -42
  176. data/lib/generators/serializer/templates/serializer.rb +0 -19
  177. data/test/association_test.rb +0 -592
  178. data/test/caching_test.rb +0 -96
  179. data/test/generators_test.rb +0 -85
  180. data/test/no_serialization_scope_test.rb +0 -34
  181. data/test/serialization_test.rb +0 -392
  182. data/test/serializer_support_test.rb +0 -51
  183. data/test/serializer_test.rb +0 -1465
  184. data/test/test_fakes.rb +0 -217
data/Rakefile CHANGED
@@ -1,18 +1,75 @@
1
- #!/usr/bin/env rake
2
- require "bundler/gem_tasks"
3
- require "rake/testtask"
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
- desc 'Run tests'
6
- Rake::TestTask.new(:test) do |t|
7
- t.libs << 'lib'
38
+ require 'rake/testtask'
39
+
40
+ Rake::TestTask.new do |t|
8
41
  t.libs << 'test'
9
- t.pattern = 'test/**/*_test.rb'
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 'Benchmark'
14
- task :bench do
15
- load 'bench/perf.rb'
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
- task :default => :test
74
+ desc 'CI test task'
75
+ task :ci => [:default]
@@ -1,24 +1,58 @@
1
- # -*- encoding: utf-8 -*-
2
-
3
- $:.unshift File.expand_path("../lib", __FILE__)
4
- require "active_model/serializers/version"
5
-
6
- Gem::Specification.new do |gem|
7
- gem.authors = ["José Valim", "Yehuda Katz"]
8
- gem.email = ["jose.valim@gmail.com", "wycats@gmail.com"]
9
- gem.description = %q{Making it easy to serialize models for client-side use}
10
- gem.summary = %q{Bringing consistency and object orientation to model serialization. Works great for client-side MVC frameworks!}
11
- gem.homepage = "https://github.com/rails-api/active_model_serializers"
12
-
13
- gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
14
- gem.files = `git ls-files`.split("\n")
15
- gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
- gem.name = "active_model_serializers"
17
- gem.require_paths = ["lib"]
18
- gem.version = ActiveModel::Serializer::VERSION
19
-
20
- gem.add_dependency 'activemodel', '>= 3.0'
21
- gem.add_development_dependency "rails", ">= 3.0"
22
- gem.add_development_dependency "pry"
23
- gem.add_development_dependency "minitest"
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
+ ```
@@ -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/