active_model_serializers 0.8.3 → 0.10.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (124) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +5 -0
  3. data/.rubocop.yml +82 -0
  4. data/.rubocop_todo.yml +315 -0
  5. data/.simplecov +99 -0
  6. data/.travis.yml +26 -20
  7. data/CHANGELOG.md +14 -67
  8. data/CONTRIBUTING.md +31 -0
  9. data/Gemfile +45 -1
  10. data/{MIT-LICENSE.txt → LICENSE.txt} +3 -2
  11. data/README.md +186 -488
  12. data/Rakefile +33 -12
  13. data/active_model_serializers.gemspec +49 -23
  14. data/appveyor.yml +25 -0
  15. data/docs/README.md +29 -0
  16. data/docs/general/adapters.md +110 -0
  17. data/docs/general/configuration_options.md +11 -0
  18. data/docs/general/getting_started.md +73 -0
  19. data/docs/howto/add_pagination_links.md +112 -0
  20. data/docs/howto/add_root_key.md +51 -0
  21. data/docs/howto/outside_controller_use.md +42 -0
  22. data/lib/action_controller/serialization.rb +31 -31
  23. data/lib/active_model/serializable_resource.rb +70 -0
  24. data/lib/active_model/serializer/adapter/flatten_json.rb +12 -0
  25. data/lib/active_model/serializer/adapter/fragment_cache.rb +75 -0
  26. data/lib/active_model/serializer/adapter/json/fragment_cache.rb +5 -0
  27. data/lib/active_model/serializer/adapter/json.rb +47 -0
  28. data/lib/active_model/serializer/adapter/json_api/fragment_cache.rb +13 -0
  29. data/lib/active_model/serializer/adapter/json_api/pagination_links.rb +50 -0
  30. data/lib/active_model/serializer/adapter/json_api.rb +158 -0
  31. data/lib/active_model/serializer/adapter/null.rb +5 -0
  32. data/lib/active_model/serializer/adapter.rb +159 -0
  33. data/lib/active_model/serializer/array_serializer.rb +40 -0
  34. data/lib/active_model/serializer/association.rb +20 -0
  35. data/lib/active_model/serializer/associations.rb +83 -219
  36. data/lib/active_model/serializer/belongs_to_reflection.rb +10 -0
  37. data/lib/active_model/serializer/collection_reflection.rb +7 -0
  38. data/lib/active_model/serializer/configuration.rb +14 -0
  39. data/lib/active_model/serializer/fieldset.rb +40 -0
  40. data/lib/active_model/serializer/has_many_reflection.rb +10 -0
  41. data/lib/active_model/serializer/has_one_reflection.rb +10 -0
  42. data/lib/active_model/serializer/lint.rb +129 -0
  43. data/lib/active_model/serializer/railtie.rb +15 -0
  44. data/lib/active_model/serializer/reflection.rb +74 -0
  45. data/lib/active_model/serializer/singular_reflection.rb +7 -0
  46. data/lib/active_model/serializer/utils.rb +35 -0
  47. data/lib/active_model/{serializers → serializer}/version.rb +1 -1
  48. data/lib/active_model/serializer.rb +121 -465
  49. data/lib/active_model_serializers.rb +26 -88
  50. data/lib/generators/serializer/USAGE +0 -3
  51. data/lib/generators/serializer/resource_override.rb +12 -0
  52. data/lib/generators/serializer/serializer_generator.rb +8 -13
  53. data/lib/generators/serializer/templates/serializer.rb.erb +8 -0
  54. data/lib/tasks/rubocop.rake +0 -0
  55. data/test/action_controller/adapter_selector_test.rb +53 -0
  56. data/test/action_controller/explicit_serializer_test.rb +134 -0
  57. data/test/action_controller/json_api/linked_test.rb +179 -0
  58. data/test/action_controller/json_api/pagination_test.rb +116 -0
  59. data/test/{serialization_scope_name_test.rb → action_controller/serialization_scope_name_test.rb} +15 -15
  60. data/test/action_controller/serialization_test.rb +420 -0
  61. data/test/active_record_test.rb +9 -0
  62. data/test/adapter/fragment_cache_test.rb +37 -0
  63. data/test/adapter/json/belongs_to_test.rb +47 -0
  64. data/test/adapter/json/collection_test.rb +82 -0
  65. data/test/adapter/json/has_many_test.rb +47 -0
  66. data/test/adapter/json_api/belongs_to_test.rb +157 -0
  67. data/test/adapter/json_api/collection_test.rb +95 -0
  68. data/test/adapter/json_api/has_many_embed_ids_test.rb +45 -0
  69. data/test/adapter/json_api/has_many_explicit_serializer_test.rb +98 -0
  70. data/test/adapter/json_api/has_many_test.rb +145 -0
  71. data/test/adapter/json_api/has_one_test.rb +81 -0
  72. data/test/adapter/json_api/json_api_test.rb +37 -0
  73. data/test/adapter/json_api/linked_test.rb +283 -0
  74. data/test/adapter/json_api/pagination_links_test.rb +115 -0
  75. data/test/adapter/json_api/resource_type_config_test.rb +59 -0
  76. data/test/adapter/json_test.rb +47 -0
  77. data/test/adapter/null_test.rb +25 -0
  78. data/test/adapter_test.rb +42 -0
  79. data/test/array_serializer_test.rb +99 -73
  80. data/test/capture_warnings.rb +65 -0
  81. data/test/fixtures/active_record.rb +56 -0
  82. data/test/fixtures/poro.rb +261 -0
  83. data/test/generators/scaffold_controller_generator_test.rb +23 -0
  84. data/test/generators/serializer_generator_test.rb +56 -0
  85. data/test/lint_test.rb +37 -0
  86. data/test/logger_test.rb +18 -0
  87. data/test/poro_test.rb +9 -0
  88. data/test/serializable_resource_test.rb +27 -0
  89. data/test/serializers/adapter_for_test.rb +170 -0
  90. data/test/serializers/association_macros_test.rb +36 -0
  91. data/test/serializers/associations_test.rb +150 -0
  92. data/test/serializers/attribute_test.rb +62 -0
  93. data/test/serializers/attributes_test.rb +57 -0
  94. data/test/serializers/cache_test.rb +165 -0
  95. data/test/serializers/configuration_test.rb +15 -0
  96. data/test/serializers/fieldset_test.rb +25 -0
  97. data/test/serializers/meta_test.rb +121 -0
  98. data/test/serializers/options_test.rb +21 -0
  99. data/test/serializers/root_test.rb +21 -0
  100. data/test/serializers/serializer_for_test.rb +65 -0
  101. data/test/support/rails_app.rb +21 -0
  102. data/test/support/serialization_testing.rb +13 -0
  103. data/test/support/simplecov.rb +6 -0
  104. data/test/support/stream_capture.rb +50 -0
  105. data/test/support/test_case.rb +5 -0
  106. data/test/test_helper.rb +48 -24
  107. data/test/utils/include_args_to_hash_test.rb +79 -0
  108. metadata +219 -47
  109. data/DESIGN.textile +0 -586
  110. data/Gemfile.edge +0 -9
  111. data/bench/perf.rb +0 -43
  112. data/cruft.md +0 -19
  113. data/lib/active_model/array_serializer.rb +0 -104
  114. data/lib/active_record/serializer_override.rb +0 -16
  115. data/lib/generators/resource_override.rb +0 -13
  116. data/lib/generators/serializer/templates/serializer.rb +0 -19
  117. data/test/association_test.rb +0 -592
  118. data/test/caching_test.rb +0 -96
  119. data/test/generators_test.rb +0 -85
  120. data/test/no_serialization_scope_test.rb +0 -34
  121. data/test/serialization_test.rb +0 -392
  122. data/test/serializer_support_test.rb +0 -51
  123. data/test/serializer_test.rb +0 -1465
  124. data/test/test_fakes.rb +0 -217
data/Rakefile CHANGED
@@ -1,18 +1,39 @@
1
- #!/usr/bin/env rake
2
- require "bundler/gem_tasks"
3
- require "rake/testtask"
1
+ begin
2
+ require 'simplecov'
3
+ rescue LoadError
4
+ end
4
5
 
5
- desc 'Run tests'
6
- Rake::TestTask.new(:test) do |t|
7
- t.libs << 'lib'
8
- t.libs << 'test'
9
- t.pattern = 'test/**/*_test.rb'
10
- t.verbose = true
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
+ if !defined?(::Rubinius)
15
+ Rake::Task[:rubocop].clear if Rake::Task.task_defined?(:rubocop)
16
+ desc 'Execute rubocop'
17
+ RuboCop::RakeTask.new(:rubocop) do |task|
18
+ task.options = ['--rails', '--display-cop-names', '--display-style-guide']
19
+ task.fail_on_error = true
20
+ end
21
+ else
22
+ desc 'No-op rubocop to avoid rbx segfault'
23
+ task :rubocop do
24
+ puts 'Skipping rubocop on rbx due to segfault'
25
+ puts 'https://github.com/rubinius/rubinius/issues/3499'
26
+ end
27
+ end
11
28
  end
12
29
 
13
- desc 'Benchmark'
14
- task :bench do
15
- load 'bench/perf.rb'
30
+ require 'rake/testtask'
31
+
32
+ Rake::TestTask.new do |t|
33
+ t.libs << 'test'
34
+ t.test_files = FileList['test/**/*_test.rb']
35
+ t.ruby_opts = ['-r./test/test_helper.rb']
36
+ t.verbose = true
16
37
  end
17
38
 
18
39
  task :default => :test
@@ -1,24 +1,50 @@
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 = '>= 1.9.3'
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
+ # Soft dependency for pagination
45
+ spec.add_development_dependency 'kaminari', ' ~> 0.16.3'
46
+ spec.add_development_dependency 'will_paginate', '~> 3.0', '>= 3.0.7'
47
+
48
+ spec.add_development_dependency 'bundler', '~> 1.6'
49
+ spec.add_development_dependency 'timecop', '~> 0.7'
24
50
  end
data/appveyor.yml ADDED
@@ -0,0 +1,25 @@
1
+ version: '{build}'
2
+
3
+ skip_tags: true
4
+
5
+ environment:
6
+ matrix:
7
+ - ruby_version: "193"
8
+ - ruby_version: "193-x64"
9
+ - ruby_version: "200"
10
+ - ruby_version: "200-x64"
11
+ - ruby_version: "21"
12
+ - ruby_version: "21-x64"
13
+
14
+ install:
15
+ - SET PATH=C:\Ruby%ruby_version%\bin;%PATH%
16
+ - ruby --version
17
+ - gem --version
18
+ - gem install bundler
19
+ - bundler --version
20
+ - bundle install --retry=3
21
+
22
+ test_script:
23
+ - bundle exec rake
24
+
25
+ build: off
data/docs/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Docs - ActiveModel::Serializer 0.10.x
2
+
3
+ This is the documentation of AMS, it's focused on the **0.10.x version.**
4
+
5
+ -----
6
+
7
+ ## General
8
+
9
+ - [Getting Started](general/getting_started.md)
10
+ - [Adapters](general/adapters.md)
11
+ - [Configuration Options](general/configuration_options.md)
12
+
13
+ ## How to
14
+
15
+ - [How to add root key](howto/add_root_key.md)
16
+ - [How to add pagination links](howto/add_pagination_links.md)
17
+ - [Using AMS Outside Of Controllers](howto/outside_controller_use.md)
18
+
19
+ ## Getting Help
20
+
21
+ If you find a bug, please report an [Issue](https://github.com/rails-api/active_model_serializers/issues/new).
22
+
23
+ If you have a question, please [post to Stack Overflow](http://stackoverflow.com/questions/tagged/active-model-serializers).
24
+
25
+ Thanks!
26
+
27
+ ## Contributing
28
+
29
+ See [CONTRIBUTING.md](https://github.com/rails-api/active_model_serializers/blob/master/CONTRIBUTING.md)
@@ -0,0 +1,110 @@
1
+ # Adapters
2
+
3
+ AMS does this through two components: **serializers** and **adapters**.
4
+ Serializers describe _which_ attributes and relationships should be serialized.
5
+ Adapters describe _how_ attributes and relationships should be serialized.
6
+ You can use one of the built-in adapters (```FlattenJSON``` is the default one) or create one by yourself, but you won't need to implement an adapter unless you wish to use a new format or media type with AMS.
7
+
8
+ ## Built in Adapters
9
+
10
+ ### FlattenJSON - Default
11
+
12
+ It's the default adapter, it generates a json response without a root key.
13
+ Doesn't follow any specifc convention.
14
+
15
+ ### JSON
16
+
17
+ It also generates a json response but always with a root key. The root key **can't be overridden**, and will be automatically defined accordingly to the objects being serialized.
18
+ Doesn't follow any specifc convention.
19
+
20
+ ### JSONAPI
21
+
22
+ This adapter follows **version 1.0** of the format specified in
23
+ [jsonapi.org/format](http://jsonapi.org/format). It will include the associated
24
+ resources in the `"included"` member when the resource names are included in the
25
+ `include` option.
26
+
27
+ ```ruby
28
+ render @posts, include: ['authors', 'comments']
29
+ ```
30
+
31
+ or
32
+
33
+ ```ruby
34
+ render @posts, include: 'authors,comments'
35
+ ```
36
+
37
+ The format of the `include` option can be either a String composed of a comma-separated list of [relationship paths](http://jsonapi.org/format/#fetching-includes), an Array of Symbols and Hashes, or a mix of both.
38
+
39
+ ## Choosing an adapter
40
+
41
+ If you want to use a specify a default adapter, such as JsonApi, you can change this in an initializer:
42
+
43
+ ```ruby
44
+ ActiveModel::Serializer.config.adapter = ActiveModel::Serializer::Adapter::JsonApi
45
+ ```
46
+
47
+ or
48
+
49
+ ```ruby
50
+ ActiveModel::Serializer.config.adapter = :json_api
51
+ ```
52
+
53
+ If you want to have a root key for each resource in your responses, you should use the Json or
54
+ JsonApi adapters instead of the default FlattenJson:
55
+
56
+ ```ruby
57
+ ActiveModel::Serializer.config.adapter = :json
58
+ ```
59
+
60
+ ## Advanced adapter configuration
61
+
62
+ ### Registering an adapter
63
+
64
+ The default adapter can be configured, as above, to use any class given to it.
65
+
66
+ An adapter may also be specified, e.g. when rendering, as a class or as a symbol.
67
+ If a symbol, then the adapter must be, e.g. `:great_example`,
68
+ `ActiveModel::Serializer::Adapter::GreatExample`, or registered.
69
+
70
+ There are two ways to register an adapter:
71
+
72
+ 1) The simplest, is to subclass `ActiveModel::Serializer::Adapter`, e.g. the below will
73
+ register the `Example::UsefulAdapter` as `:useful_adapter`.
74
+
75
+ ```ruby
76
+ module Example
77
+ class UsefulAdapter < ActiveModel::Serializer::Adapter
78
+ end
79
+ end
80
+ ```
81
+
82
+ You'll notice that the name it registers is the class name underscored, not the full namespace.
83
+
84
+ Under the covers, when the `ActiveModel::Serializer::Adapter` is subclassed, it registers
85
+ the subclass as `register(:useful_adapter, Example::UsefulAdapter)`
86
+
87
+ 2) Any class can be registered as an adapter by calling `register` directly on the
88
+ `ActiveModel::Serializer::Adapter` class. e.g., the below registers `MyAdapter` as
89
+ `:special_adapter`.
90
+
91
+ ```ruby
92
+ class MyAdapter; end
93
+ ActiveModel::Serializer::Adapter.register(:special_adapter, MyAdapter)
94
+ ```
95
+
96
+ ### Looking up an adapter
97
+
98
+ | Method | Return value |
99
+ | :------------ |:---------------|
100
+ | `ActiveModel::Serializer::Adapter.adapter_map` | A Hash of all known adapters `{ adapter_name => adapter_class }` |
101
+ | `ActiveModel::Serializer::Adapter.adapters` | A (sorted) Array of all known `adapter_names` |
102
+ | `ActiveModel::Serializer::Adapter.lookup(name_or_klass)` | The `adapter_class`, else raises an `ActiveModel::Serializer::Adapter::UnknownAdapter` error |
103
+ | `ActiveModel::Serializer::Adapter.adapter_class(adapter)` | Delegates to `ActiveModel::Serializer::Adapter.lookup(adapter)` |
104
+ | `ActiveModel::Serializer.adapter` | A convenience method for `ActiveModel::Serializer::Adapter.lookup(config.adapter)` |
105
+
106
+ The registered adapter name is always a String, but may be looked up as a Symbol or String.
107
+ Helpfully, the Symbol or String is underscored, so that `get(:my_adapter)` and `get("MyAdapter")`
108
+ may both be used.
109
+
110
+ For more information, see [the Adapter class on GitHub](https://github.com/rails-api/active_model_serializers/blob/master/lib/active_model/serializer/adapter.rb)
@@ -0,0 +1,11 @@
1
+ # Configuration Options
2
+
3
+ The following configuration options can be set on `ActiveModel::Serializer.config` inside an initializer.
4
+
5
+ ## General
6
+
7
+ - `adapter`: The [adapter](adapters.md) to use. Possible values: `:flatten_json, :json, :json_api`. Default: `:flatten_json`.
8
+
9
+ ## JSON API
10
+
11
+ - `jsonapi_resource_type`: Whether the `type` attributes of resources should be singular or plural. Possible values: `:singular, :plural`. Default: `:plural`.
@@ -0,0 +1,73 @@
1
+ # Getting Started
2
+
3
+ ## Installation
4
+
5
+ ### ActiveModel::Serializer is already included on Rails >= 5
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```
10
+ gem 'active_model_serializers'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ ```
16
+ $ bundle
17
+ ```
18
+
19
+ ## Creating a Serializer
20
+
21
+ The easiest way to create a new serializer is to generate a new resource, which
22
+ will generate a serializer at the same time:
23
+
24
+ ```
25
+ $ rails g resource post title:string body:string
26
+ ```
27
+
28
+ This will generate a serializer in `app/serializers/post_serializer.rb` for
29
+ your new model. You can also generate a serializer for an existing model with
30
+ the serializer generator:
31
+
32
+ ```
33
+ $ rails g serializer post
34
+ ```
35
+
36
+ The generated seralizer will contain basic `attributes` and
37
+ `has_many`/`has_one`/`belongs_to` declarations, based on the model. For example:
38
+
39
+ ```ruby
40
+ class PostSerializer < ActiveModel::Serializer
41
+ attributes :title, :body
42
+
43
+ has_many :comments
44
+ has_one :author
45
+
46
+ end
47
+ ```
48
+
49
+ and
50
+
51
+ ```ruby
52
+ class CommentSerializer < ActiveModel::Serializer
53
+ attributes :name, :body
54
+
55
+ belongs_to :post_id
56
+
57
+ end
58
+ ```
59
+
60
+ ## Rails Integration
61
+
62
+ AMS will automatically integrate with you Rails app, you won't need to update your controller, this is a example of how it will look like:
63
+
64
+ ```ruby
65
+ class PostsController < ApplicationController
66
+
67
+ def show
68
+ @post = Post.find(params[:id])
69
+ render json: @post
70
+ end
71
+
72
+ end
73
+ ```
@@ -0,0 +1,112 @@
1
+ # How to add pagination links
2
+
3
+ ### JSON-API adapter
4
+
5
+ Pagination links will be included in your response automatically as long as the resource is paginated and if you are using a ```JSON-API``` adapter.
6
+
7
+ If you want pagination links in your response, use [Kaminari](https://github.com/amatsuda/kaminari) or [WillPaginate](https://github.com/mislav/will_paginate).
8
+
9
+ ###### Kaminari examples
10
+ ```ruby
11
+ #array
12
+ @posts = Kaminari.paginate_array([1, 2, 3]).page(3).per(1)
13
+ render json: @posts
14
+
15
+ #active_record
16
+ @posts = Post.page(3).per(1)
17
+ render json: @posts
18
+ ```
19
+
20
+ ###### WillPaginate examples
21
+
22
+ ```ruby
23
+ #array
24
+ @posts = [1,2,3].paginate(page: 3, per_page: 1)
25
+ render json: @posts
26
+
27
+ #active_record
28
+ @posts = Post.page(3).per_page(1)
29
+ render json: @posts
30
+ ```
31
+
32
+ ```ruby
33
+ ActiveModel::Serializer.config.adapter = :json_api
34
+ ```
35
+
36
+ ex:
37
+ ```json
38
+ {
39
+ "data": [
40
+ {
41
+ "type": "articles",
42
+ "id": "3",
43
+ "attributes": {
44
+ "title": "JSON API paints my bikeshed!",
45
+ "body": "The shortest article. Ever.",
46
+ "created": "2015-05-22T14:56:29.000Z",
47
+ "updated": "2015-05-22T14:56:28.000Z"
48
+ }
49
+ }
50
+ ],
51
+ "links": {
52
+ "self": "http://example.com/articles?page[number]=3&page[size]=1",
53
+ "first": "http://example.com/articles?page[number]=1&page[size]=1",
54
+ "prev": "http://example.com/articles?page[number]=2&page[size]=1",
55
+ "next": "http://example.com/articles?page[number]=4&page[size]=1",
56
+ "last": "http://example.com/articles?page[number]=13&page[size]=1"
57
+ }
58
+ }
59
+ ```
60
+
61
+ AMS pagination relies on a paginated collection with the methods `current_page`, `total_pages`, and `size`, such as are supported by both [Kaminari](https://github.com/amatsuda/kaminari) or [WillPaginate](https://github.com/mislav/will_paginate).
62
+
63
+
64
+ ### JSON adapter
65
+
66
+ If you are using `JSON` adapter, pagination links will not be included automatically, but it is possible to do so using `meta` key.
67
+
68
+ In your action specify a custom serializer.
69
+ ```ruby
70
+ render json: @posts, serializer: PaginatedSerializer, each_serializer: PostPreviewSerializer
71
+ ```
72
+
73
+ And then, you could do something like the following class.
74
+ ```ruby
75
+ class PaginatedSerializer < ActiveModel::Serializer::ArraySerializer
76
+ def initialize(object, options={})
77
+ meta_key = options[:meta_key] || :meta
78
+ options[meta_key] ||= {}
79
+ options[meta_key] = {
80
+ current_page: object.current_page,
81
+ next_page: object.next_page,
82
+ prev_page: object.prev_page,
83
+ total_pages: object.total_pages,
84
+ total_count: object.total_count
85
+ }
86
+ super(object, options)
87
+ end
88
+ end
89
+ ```
90
+ ex.
91
+ ```json
92
+ {
93
+ "articles": [
94
+ {
95
+ "id": 2,
96
+ "title": "JSON API paints my bikeshed!",
97
+ "body": "The shortest article. Ever."
98
+ }
99
+ ],
100
+ "meta": {
101
+ "current_page": 3,
102
+ "next_page": 4,
103
+ "prev_page": 2,
104
+ "total_pages": 10,
105
+ "total_count": 10
106
+ }
107
+ }
108
+ ```
109
+
110
+ ### FlattenJSON adapter
111
+
112
+ This adapter does not allow us to use `meta` key, due to that it is not possible to add pagination links.
@@ -0,0 +1,51 @@
1
+ # How to add root key
2
+
3
+ Add the root key to your API is quite simple with AMS. The **Adapter** is what determines the format of your JSON response. The default adapter is the ```FlattenJSON``` which doesn't have the root key, so your response is something similar to:
4
+
5
+ ```json
6
+ {
7
+ "id": 1,
8
+ "title": "Awesome Post Tile",
9
+ "content": "Post content"
10
+ }
11
+ ```
12
+
13
+ In order to add the root key you need to use the ```JSON``` Adapter, you can change this in an initializer:
14
+
15
+ ```ruby
16
+ ActiveModel::Serializer.config.adapter = :json
17
+ ```
18
+
19
+ You can also specify a class as adapter, as long as it complies with the AMS adapters interface.
20
+ It will add the root key to all your serialized endpoints.
21
+
22
+ ex:
23
+
24
+ ```json
25
+ {
26
+ "post": {
27
+ "id": 1,
28
+ "title": "Awesome Post Tile",
29
+ "content": "Post content"
30
+ }
31
+ }
32
+ ```
33
+
34
+ or if it returns a collection:
35
+
36
+ ```json
37
+ {
38
+ "posts": [
39
+ {
40
+ "id": 1,
41
+ "title": "Awesome Post Tile",
42
+ "content": "Post content"
43
+ },
44
+ {
45
+ "id": 2,
46
+ "title": "Another Post Tile",
47
+ "content": "Another post content"
48
+ }
49
+ ]
50
+ }
51
+ ```
@@ -0,0 +1,42 @@
1
+ ## Using AMS Outside Of A Controller
2
+
3
+ ### Serializing a resource
4
+
5
+ In AMS versions 0.10 or later, serializing resources outside of the controller context is fairly simple:
6
+
7
+ ```ruby
8
+ # Create our resource
9
+ post = Post.create(title: "Sample post", body: "I love Active Model Serializers!")
10
+
11
+ # Optional options parameters
12
+ options = {}
13
+
14
+ # Create a serializable resource instance
15
+ serializable_resource = ActiveModel::SerializableResource.new(post, options)
16
+
17
+ # Convert your resource into json
18
+ model_json = serializable_resource.as_json
19
+ ```
20
+
21
+ ### Retrieving a Resource's Active Model Serializer
22
+
23
+ If you want to retrieve a serializer for a specific resource, you can do the following:
24
+
25
+ ```ruby
26
+ # Create our resource
27
+ post = Post.create(title: "Another Example", body: "So much fun.")
28
+
29
+ # Optional options parameters
30
+ options = {}
31
+
32
+ # Retrieve the default serializer for posts
33
+ serializer = ActiveModel::Serializer.serializer_for(post, options)
34
+ ```
35
+
36
+ You could also retrieve the serializer via:
37
+
38
+ ```ruby
39
+ ActiveModel::SerializableResource.new(post, options).serializer
40
+ ```
41
+
42
+ Both approaches will return an instance, if any, of the resource's serializer.
@@ -1,32 +1,14 @@
1
+ require 'active_support/core_ext/class/attribute'
2
+
1
3
  module ActionController
2
- # Action Controller Serialization
3
- #
4
- # Overrides render :json to check if the given object implements +active_model_serializer+
5
- # as a method. If so, use the returned serializer instead of calling +to_json+ on the object.
6
- #
7
- # This module also provides a serialization_scope method that allows you to configure the
8
- # +serialization_scope+ of the serializer. Most apps will likely set the +serialization_scope+
9
- # to the current user:
10
- #
11
- # class ApplicationController < ActionController::Base
12
- # serialization_scope :current_user
13
- # end
14
- #
15
- # If you need more complex scope rules, you can simply override the serialization_scope:
16
- #
17
- # class ApplicationController < ActionController::Base
18
- # private
19
- #
20
- # def serialization_scope
21
- # current_user
22
- # end
23
- # end
24
- #
25
4
  module Serialization
26
5
  extend ActiveSupport::Concern
27
6
 
28
7
  include ActionController::Renderers
29
8
 
9
+ # Deprecated
10
+ ADAPTER_OPTION_KEYS = ActiveModel::SerializableResource::ADAPTER_OPTION_KEYS
11
+
30
12
  included do
31
13
  class_attribute :_serialization_scope
32
14
  self._serialization_scope = :current_user
@@ -37,18 +19,36 @@ module ActionController
37
19
  respond_to?(_serialization_scope, true)
38
20
  end
39
21
 
40
- def default_serializer_options
22
+ def get_serializer(resource, options = {})
23
+ if !use_adapter?
24
+ warn 'ActionController::Serialization#use_adapter? has been removed. '\
25
+ "Please pass 'adapter: false' or see ActiveSupport::SerializableResource.new"
26
+ options[:adapter] = false
27
+ end
28
+ serializable_resource = ActiveModel::SerializableResource.new(resource, options)
29
+ if serializable_resource.serializer?
30
+ serializable_resource.serialization_scope ||= serialization_scope
31
+ serializable_resource.serialization_scope_name = _serialization_scope
32
+ begin
33
+ serializable_resource.adapter
34
+ rescue ActiveModel::Serializer::ArraySerializer::NoSerializerError
35
+ resource
36
+ end
37
+ else
38
+ resource
39
+ end
40
+ end
41
+
42
+ # Deprecated
43
+ def use_adapter?
44
+ true
41
45
  end
42
46
 
43
47
  [:_render_option_json, :_render_with_renderer_json].each do |renderer_method|
44
48
  define_method renderer_method do |resource, options|
45
- json = ActiveModel::Serializer.build_json(self, resource, options)
46
-
47
- if json
48
- super(json, options)
49
- else
50
- super(resource, options)
51
- end
49
+ options.fetch(:context) { options[:context] = request }
50
+ serializable_resource = get_serializer(resource, options)
51
+ super(serializable_resource, options)
52
52
  end
53
53
  end
54
54