Compare commits

...

No commits in common. "v0.9.8" and "master" have entirely different histories.

83 changed files with 1012 additions and 6515 deletions

29
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,29 @@
#### Expected behavior vs actual behavior
#### Steps to reproduce
*(e.g., detailed walkthrough, runnable script, example application)*
#### Environment
ActiveModelSerializers Version *(commit ref if not on tag)*:
Output of `ruby -e "puts RUBY_DESCRIPTION"`:
OS Type & Version:
Integrated application and version *(e.g., Rails, Grape, etc)*:
#### Backtrace
*(e.g., provide any applicable backtraces from your application)*
#### Additonal helpful information
*(e.g., Gemfile.lock, configurations, PR containing a failing test, git bisect results)*

15
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,15 @@
#### Purpose
#### Changes
#### Caveats
#### Related GitHub issues
#### Additional helpful information

17
.gitignore vendored
View File

@ -3,13 +3,16 @@
.bundle
.config
.yardoc
*.lock
Gemfile.lock
Gemfile.local
InstalledFiles
_yardoc
coverage
doc/
lib/bundler/man
pkg
Vagrantfile
.vagrant
rdoc
spec/reports
test/tmp
@ -17,4 +20,16 @@ test/version_tmp
tmp
*.swp
.ruby-version
.ruby-gemset
vendor/bundle
tags
# silly macs
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
Icon?
ehthumbs.db
Thumbs.db

View File

@ -2,54 +2,9 @@ language: ruby
sudo: false
rvm:
- 1.9.3 # EOL
- 2.0.0 # EOL
- 2.1
- ruby-head
- jruby-9.1.5.0 # is precompiled per http://rubies.travis-ci.org/
jdk:
- openjdk8
before_install:
- gem update --system 2.6.8
- if [ "$RUBY_VERSION" != "jruby-9.1.5.0" ] ; then update_rubygems ; fi
- rvm @global do gem install bundler -v 1.13.7
install: bundle _1.13.7_ install --path=vendor/bundle --retry=3 --jobs=3
cache:
directories:
- vendor/bundle
env:
global:
- "JRUBY_OPTS='--dev -J-Xmx1024M --debug'"
matrix:
- "RAILS_VERSION=4.0"
- "RAILS_VERSION=4.1"
- "RAILS_VERSION=4.2"
- "RAILS_VERSION=5.0"
- "RAILS_VERSION=master"
matrix:
exclude:
- rvm: 1.9.3
env: RAILS_VERSION=master
- rvm: 2.0.0
env: RAILS_VERSION=master
- rvm: 2.1
env: RAILS_VERSION=master
- rvm: jruby-9.1.5.0
env: RAILS_VERSION=master
- rvm: 1.9.3
env: RAILS_VERSION=5.0
- rvm: 2.0.0
env: RAILS_VERSION=5.0
- rvm: 2.1
env: RAILS_VERSION=5.0
- rvm: jruby-9.1.5.0
env: RAILS_VERSION=5.0
allow_failures:
- rvm: ruby-head
- env: "RAILS_VERSION=master"
fast_finish: true
script:
- true

92
CHANGELOG-0-08.md Normal file
View File

@ -0,0 +1,92 @@
## 0.08.x
### v0.8.3 (2014/12/10 14:45 +00:00)
- [#753](https://github.com/rails-api/active_model_serializers/pull/753) Test against Ruby 2.2 on Travis CI (@tricknotes)
- [#745](https://github.com/rails-api/active_model_serializers/pull/745) Missing a word (@jockee)
### v0.8.2 (2014/09/01 21:00 +00:00)
- [#612](https://github.com/rails-api/active_model_serializers/pull/612) Feature/adapter (@bolshakov)
* adds adapters pattern
- [#615](https://github.com/rails-api/active_model_serializers/pull/615) Rails does not support const_defined? in development mode (@tpitale)
- [#613](https://github.com/rails-api/active_model_serializers/pull/613) README: typo fix on attributes (@spk)
- [#614](https://github.com/rails-api/active_model_serializers/pull/614) Fix rails 4.0.x build. (@arthurnn)
- [#610](https://github.com/rails-api/active_model_serializers/pull/610) ArraySerializer (@bolshakov)
- [#607](https://github.com/rails-api/active_model_serializers/pull/607) ruby syntax highlights (@zigomir)
- [#602](https://github.com/rails-api/active_model_serializers/pull/602) Add DSL for associations (@JordanFaust)
### 0.8.1 (May 6, 2013)
* Fix bug whereby a serializer using 'options' would blow up.
### 0.8.0 (May 5, 2013)
* Attributes can now have optional types.
* A new DefaultSerializer ensures that POROs behave the same way as ActiveModels.
* If you wish to override ActiveRecord::Base#to_Json, you can now require
'active_record/serializer_override'. We don't recommend you do this, but
many users do, so we've left it optional.
* Fixed a bug where ActionController wouldn't always have MimeResponds.
* An optinal caching feature allows you to cache JSON & hashes that AMS uses.
Adding 'cached true' to your Serializers will turn on this cache.
* URL helpers used inside of Engines now work properly.
* Serializers now can filter attributes with `only` and `except`:
```
UserSerializer.new(user, only: [:first_name, :last_name])
UserSerializer.new(user, except: :first_name)
```
* Basic Mongoid support. We now include our mixins in the right place.
* On Ruby 1.8, we now generate an `id` method that properly serializes `id`
columns. See issue #127 for more.
* Add an alias for `scope` method to be the name of the context. By default
this is `current_user`. The name is automatically set when using
`serialization_scope` in the controller.
* Pass through serialization options (such as `:include`) when a model
has no serializer defined.
## [0.7.0 (March 6, 2013)](https://github.com/rails-api/active_model_serializers/commit/fabdc621ff97fbeca317f6301973dd4564b9e695)
* ```embed_key``` option to allow embedding by attributes other than IDs
* Fix rendering nil with custom serializer
* Fix global ```self.root = false```
* Add support for specifying the serializer for an association as a String
* Able to specify keys on the attributes method
* Serializer Reloading via ActiveSupport::DescendantsTracker
* Reduce double map to once; Fixes datamapper eager loading.
## 0.6.0 (October 22, 2012)
* Serialize sets properly
* Add root option to ArraySerializer
* Support polymorphic associations
* Support :each_serializer in ArraySerializer
* Add `scope` method to easily access the scope in the serializer
* Fix regression with Rails 3.2.6; add Rails 4 support
* Allow serialization_scope to be disabled with serialization_scope nil
* Array serializer should support pure ruby objects besides serializers
## 0.05.x
### [0.5.2 (June 5, 2012)](https://github.com/rails-api/active_model_serializers/commit/615afd125c260432d456dc8be845867cf87ea118#diff-0c5c12f311d3b54734fff06069efd2ac)
### [0.5.1 (May 23, 2012)](https://github.com/rails-api/active_model_serializers/commit/00194ec0e41831802fcbf893a34c0bb0853ebe14#diff-0c5c12f311d3b54734fff06069efd2ac)
### [0.5.0 (May 16, 2012)](https://github.com/rails-api/active_model_serializers/commit/33d4842dcd35c7167b0b33fc0abcf00fb2c92286)
* First tagged version
* Changes generators to always generate an ApplicationSerializer
## [0.1.0 (December 21, 2011)](https://github.com/rails-api/active_model_serializers/commit/1e0c9ef93b96c640381575dcd30be07ac946818b)
## First Commit as [Rails Serializers 0.0.1](https://github.com/rails-api/active_model_serializers/commit/d72b66d4c5355b0ff0a75a04895fcc4ea5b0c65e)
(December 1, 2011).

74
CHANGELOG-0-09.md Normal file
View File

@ -0,0 +1,74 @@
## 0.09.x
### v0.9.3 (2015/01/21 20:29 +00:00)
Features:
- [#774](https://github.com/rails-api/active_model_serializers/pull/774) Fix nested include attributes (@nhocki)
- [#771](https://github.com/rails-api/active_model_serializers/pull/771) Make linked resource type names consistent with root names (@sweatypitts)
- [#696](https://github.com/rails-api/active_model_serializers/pull/696) Explicitly set serializer for associations (@ggordon)
- [#700](https://github.com/rails-api/active_model_serializers/pull/700) sparse fieldsets (@arenoir)
- [#768](https://github.com/rails-api/active_model_serializers/pull/768) Adds support for `meta` and `meta_key` attribute (@kurko)
### v0.9.1 (2014/12/04 11:54 +00:00)
- [#707](https://github.com/rails-api/active_model_serializers/pull/707) A Friendly Note on Which AMS Version to Use (@jherdman)
- [#730](https://github.com/rails-api/active_model_serializers/pull/730) Fixes nested has_many links in JSONAPI (@kurko)
- [#718](https://github.com/rails-api/active_model_serializers/pull/718) Allow overriding the adapter with render option (@ggordon)
- [#720](https://github.com/rails-api/active_model_serializers/pull/720) Rename attribute with :key (0.8.x compatibility) (@ggordon)
- [#728](https://github.com/rails-api/active_model_serializers/pull/728) Use type as key for linked resources (@kurko)
- [#729](https://github.com/rails-api/active_model_serializers/pull/729) Use the new beta build env on Travis (@joshk)
- [#703](https://github.com/rails-api/active_model_serializers/pull/703) Support serializer and each_serializer options in renderer (@ggordon, @mieko)
- [#727](https://github.com/rails-api/active_model_serializers/pull/727) Includes links inside of linked resources (@kurko)
- [#726](https://github.com/rails-api/active_model_serializers/pull/726) Bugfix: include nested has_many associations (@kurko)
- [#722](https://github.com/rails-api/active_model_serializers/pull/722) Fix infinite recursion (@ggordon)
- [#1](https://github.com/rails-api/active_model_serializers/pull/1) Allow for the implicit use of ArraySerializer when :each_serializer is specified (@mieko)
- [#692](https://github.com/rails-api/active_model_serializers/pull/692) Include 'linked' member for json-api collections (@ggordon)
- [#714](https://github.com/rails-api/active_model_serializers/pull/714) Define as_json instead of to_json (@guilleiguaran)
- [#710](https://github.com/rails-api/active_model_serializers/pull/710) JSON-API: Don't include linked section if associations are empty (@guilleiguaran)
- [#711](https://github.com/rails-api/active_model_serializers/pull/711) Fixes rbx gems bundling on TravisCI (@kurko)
- [#709](https://github.com/rails-api/active_model_serializers/pull/709) Add type key when association name is different than object type (@guilleiguaran)
- [#708](https://github.com/rails-api/active_model_serializers/pull/708) Handle correctly null associations (@guilleiguaran)
- [#691](https://github.com/rails-api/active_model_serializers/pull/691) Fix embed option for associations (@jacob-s-son)
- [#689](https://github.com/rails-api/active_model_serializers/pull/689) Fix support for custom root in JSON-API adapter (@guilleiguaran)
- [#685](https://github.com/rails-api/active_model_serializers/pull/685) Serialize ids as strings in JSON-API adapter (@guilleiguaran)
- [#684](https://github.com/rails-api/active_model_serializers/pull/684) Refactor adapters to implement support for array serialization (@guilleiguaran)
- [#682](https://github.com/rails-api/active_model_serializers/pull/682) Include root by default in JSON-API serializers (@guilleiguaran)
- [#625](https://github.com/rails-api/active_model_serializers/pull/625) Add DSL for urls (@JordanFaust)
- [#677](https://github.com/rails-api/active_model_serializers/pull/677) Add support for embed: :ids option for in associations (@guilleiguaran)
- [#681](https://github.com/rails-api/active_model_serializers/pull/681) Check superclasses for Serializers (@quainjn)
- [#680](https://github.com/rails-api/active_model_serializers/pull/680) Add support for root keys (@NullVoxPopuli)
- [#675](https://github.com/rails-api/active_model_serializers/pull/675) Support Rails 4.2.0 (@tricknotes)
- [#667](https://github.com/rails-api/active_model_serializers/pull/667) Require only activemodel instead of full rails (@guilleiguaran)
- [#653](https://github.com/rails-api/active_model_serializers/pull/653) Add "_test" suffix to JsonApi::HasManyTest filename. (@alexgenco)
- [#631](https://github.com/rails-api/active_model_serializers/pull/631) Update build badge URL (@craiglittle)
### 0.9.0.alpha1 - January 7, 2014
### 0.9.0.pre
* The following methods were removed
- Model#active\_model\_serializer
- Serializer#include!
- Serializer#include?
- Serializer#attr\_disabled=
- Serializer#cache
- Serializer#perform\_caching
- Serializer#schema (needs more discussion)
- Serializer#attribute
- Serializer#include\_#{name}? (filter method added)
- Serializer#attributes (took a hash)
* The following things were added
- Serializer#filter method
- CONFIG object
* Remove support for ruby 1.8 versions.
* Require rails >= 3.2.
* Serializers for associations are being looked up in a parent serializer's namespace first. Same with controllers' namespaces.
* Added a "prefix" option in case you want to use a different version of serializer.
* Serializers default namespace can be set in `default_serializer_options` and inherited by associations.
* [Beginning of rewrite: c65d387705ec534db171712671ba7fcda4f49f68](https://github.com/rails-api/active_model_serializers/commit/c65d387705ec534db171712671ba7fcda4f49f68)

466
CHANGELOG-0-10.md Normal file
View File

@ -0,0 +1,466 @@
## 0.10.x
### [0-10-stable (unreleased)](https://github.com/rails-api/active_model_serializers/compare/v0.10.6...0-10-stable)
Breaking changes:
Features:
Fixes:
Misc:
### [v0.10.6 (2017-05-01)](https://github.com/rails-api/active_model_serializers/compare/v0.10.5...v0.10.6)
Fixes:
- [#1857](https://github.com/rails-api/active_model_serializers/pull/1857) JSON:API does not load belongs_to relation to get identifier id. (@bf4)
- [#2119](https://github.com/rails-api/active_model_serializers/pull/2119) JSON:API returns null resource object identifier when 'id' is null. (@bf4)
- [#2093](https://github.com/rails-api/active_model_serializers/pull/2093) undef problematic Serializer methods: display, select. (@bf4)
Misc:
- [#2104](https://github.com/rails-api/active_model_serializers/pull/2104) Documentation for serializers and rendering. (@cassidycodes)
- [#2081](https://github.com/rails-api/active_model_serializers/pull/2081) Documentation for `include` option in adapters. (@charlie-wasp)
- [#2120](https://github.com/rails-api/active_model_serializers/pull/2120) Documentation for association options: foreign_key, type, class_name, namespace. (@bf4)
### [v0.10.5 (2017-03-07)](https://github.com/rails-api/active_model_serializers/compare/v0.10.4...v0.10.5)
Breaking changes:
Features:
- [#2021](https://github.com/rails-api/active_model_serializers/pull/2021) ActiveModelSerializers::Model#attributes. Originally in [#1982](https://github.com/rails-api/active_model_serializers/pull/1982). (@bf4)
- [#2057](https://github.com/rails-api/active_model_serializers/pull/2057)
Update version constraint for jsonapi-renderer to `['>= 0.1.1.beta1', '< 0.2']`
(@jaredbeck)
Fixes:
- [#2022](https://github.com/rails-api/active_model_serializers/pull/2022) Mutation of ActiveModelSerializers::Model now changes the attributes. Originally in [#1984](https://github.com/rails-api/active_model_serializers/pull/1984). (@bf4)
Misc:
- [#2055](https://github.com/rails-api/active_model_serializers/pull/2055)
Replace deprecated dependency jsonapi with jsonapi-renderer. (@jaredbeck)
- [#2021](https://github.com/rails-api/active_model_serializers/pull/2021) Make test attributes explicit. Tests have Model#associations. (@bf4)
- [#1981](https://github.com/rails-api/active_model_serializers/pull/1981) Fix relationship link documentation. (@groyoh)
- [#2035](https://github.com/rails-api/active_model_serializers/pull/2035) Document how to disable the logger. (@MSathieu)
- [#2039](https://github.com/rails-api/active_model_serializers/pull/2039) Documentation fixes. (@biow0lf)
### [v0.10.4 (2017-01-06)](https://github.com/rails-api/active_model_serializers/compare/v0.10.3...v0.10.4)
Misc:
- [#2005](https://github.com/rails-api/active_model_serializers/pull/2005) Update jsonapi runtime dependency to 0.1.1.beta6, support Ruby 2.4. (@kofronpi)
- [#1993](https://github.com/rails-api/active_model_serializers/pull/1993) Swap out KeyTransform for CaseTransform gem for the possibility of native extension use. (@NullVoxPopuli)
### [v0.10.3 (2016-11-21)](https://github.com/rails-api/active_model_serializers/compare/v0.10.2...v0.10.3)
Fixes:
- [#1973](https://github.com/rails-api/active_model_serializers/pull/1973) Fix namespace lookup for collections and has_many relationships (@groyoh)
- [#1887](https://github.com/rails-api/active_model_serializers/pull/1887) Make the comment reflect what the function does (@johnnymo87)
- [#1890](https://github.com/rails-api/active_model_serializers/issues/1890) Ensure generator inherits from ApplicationSerializer when available (@richmolj)
- [#1922](https://github.com/rails-api/active_model_serializers/pull/1922) Make railtie an optional dependency in runtime (@ggpasqualino)
- [#1930](https://github.com/rails-api/active_model_serializers/pull/1930) Ensure valid jsonapi when relationship has no links or data (@richmolj)
Features:
- [#1757](https://github.com/rails-api/active_model_serializers/pull/1757) Make serializer lookup chain configurable. (@NullVoxPopuli)
- [#1968](https://github.com/rails-api/active_model_serializers/pull/1968) (@NullVoxPopuli)
- Add controller namespace to default controller lookup
- Provide a `namespace` render option
- document how set the namespace in the controller for implicit lookup.
- [#1791](https://github.com/rails-api/active_model_serializers/pull/1791) (@bf4, @youroff, @NullVoxPopuli)
- Added `jsonapi_namespace_separator` config option.
- [#1889](https://github.com/rails-api/active_model_serializers/pull/1889) Support key transformation for Attributes adapter (@iancanderson, @danbee)
- [#1917](https://github.com/rails-api/active_model_serializers/pull/1917) Add `jsonapi_pagination_links_enabled` configuration option (@richmolj)
- [#1797](https://github.com/rails-api/active_model_serializers/pull/1797) Only include 'relationships' when sideloading (@richmolj)
Fixes:
- [#1833](https://github.com/rails-api/active_model_serializers/pull/1833) Remove relationship links if they are null (@groyoh)
- [#1881](https://github.com/rails-api/active_model_serializers/pull/1881) ActiveModelSerializers::Model correctly works with string keys (@yevhene)
Misc:
- [#1767](https://github.com/rails-api/active_model_serializers/pull/1767) Replace raising/rescuing `CollectionSerializer::NoSerializerError`,
throw/catch `:no_serializer`. (@bf4)
- [#1839](https://github.com/rails-api/active_model_serializers/pull/1839) `fields` tests demonstrating usage for both attributes and relationships. (@NullVoxPopuli)
- [#1812](https://github.com/rails-api/active_model_serializers/pull/1812) add a code of conduct (@corainchicago)
- [#1878](https://github.com/rails-api/active_model_serializers/pull/1878) Cache key generation for serializers now uses `ActiveSupport::Cache.expand_cache_key` instead of `Array#join` by default and is also overridable. This change should be backward-compatible. (@markiz)
- [#1799](https://github.com/rails-api/active_model_serializers/pull/1799) Add documentation for setting the adapter. (@cassidycodes)
- [#1909](https://github.com/rails-api/active_model_serializers/pull/1909) Add documentation for relationship links. (@vasilakisfil, @NullVoxPopuli)
- [#1959](https://github.com/rails-api/active_model_serializers/pull/1959) Add documentation for root. (@shunsuke227ono)
- [#1967](https://github.com/rails-api/active_model_serializers/pull/1967) Improve type method documentation. (@yukideluxe)
### [v0.10.2 (2016-07-05)](https://github.com/rails-api/active_model_serializers/compare/v0.10.1...v0.10.2)
Fixes:
- [#1814](https://github.com/rails-api/active_model_serializers/pull/1814) Ensuring read_multi works with fragment cache
- [#1848](https://github.com/rails-api/active_model_serializers/pull/1848) Redefine associations on inherited serializers. (@EhsanYousefi)
Misc:
- [#1808](https://github.com/rails-api/active_model_serializers/pull/1808) Adds documentation for `fields` option. (@luizkowalski)
### [v0.10.1 (2016-06-16)](https://github.com/rails-api/active_model_serializers/compare/v0.10.0...v0.10.1)
Features:
- [#1668](https://github.com/rails-api/active_model_serializers/pull/1668) Exclude nil and empty links. (@sigmike)
- [#1426](https://github.com/rails-api/active_model_serializers/pull/1426) Add ActiveModelSerializers.config.default_includes (@empact)
Fixes:
- [#1754](https://github.com/rails-api/active_model_serializers/pull/1754) Fixes #1759, Grape integration, improves serialization_context
missing error message on pagination. Document overriding CollectionSerializer#paginated?. (@bf4)
Moved serialization_context creation to Grape formatter, so resource serialization works without explicit calls to the `render` helper method.
Added Grape collection tests. (@onomated)
- [#1287](https://github.com/rails-api/active_model_serializers/pull/1287) Pass `fields` options from adapter to serializer. (@vasilakisfil)
- [#1710](https://github.com/rails-api/active_model_serializers/pull/1710) Prevent association loading when `include_data` option
is set to `false`. (@groyoh)
- [#1747](https://github.com/rails-api/active_model_serializers/pull/1747) Improve jsonapi mime type registration for Rails 5 (@remear)
Misc:
- [#1734](https://github.com/rails-api/active_model_serializers/pull/1734) Adds documentation for conditional attribute (@lambda2)
- [#1685](https://github.com/rails-api/active_model_serializers/pull/1685) Replace `IncludeTree` with `IncludeDirective` from the jsonapi gem.
### [v0.10.0 (2016-05-17)](https://github.com/rails-api/active_model_serializers/compare/4a2d9853ba7...v0.10.0)
Breaking changes:
- [#1662](https://github.com/rails-api/active_model_serializers/pull/1662) Drop support for Rails 4.0 and Ruby 2.0.0. (@remear)
Features:
- [#1677](https://github.com/rails-api/active_model_serializers/pull/1677) Add `assert_schema`, `assert_request_schema`, `assert_request_response_schema`. (@bf4)
- [#1697](https://github.com/rails-api/active_model_serializers/pull/1697) Include actual exception message with custom exceptions;
`Test::Schema` exceptions are now `Minitest::Assertion`s. (@bf4)
- [#1699](https://github.com/rails-api/active_model_serializers/pull/1699) String/Lambda support for conditional attributes/associations (@mtsmfm)
- [#1687](https://github.com/rails-api/active_model_serializers/pull/1687) Only calculate `_cache_digest` (in `cache_key`) when `skip_digest` is false. (@bf4)
- [#1647](https://github.com/rails-api/active_model_serializers/pull/1647) Restrict usage of `serializable_hash` options
to the ActiveModel::Serialization and ActiveModel::Serializers::JSON interface. (@bf4)
Fixes:
- [#1700](https://github.com/rails-api/active_model_serializers/pull/1700) Support pagination link for Kaminari when no data is returned. (@iamnader)
- [#1726](https://github.com/rails-api/active_model_serializers/pull/1726) Adds polymorphic option to association definition which includes association type/nesting in serializer (@cgmckeever)
Misc:
- [#1673](https://github.com/rails-api/active_model_serializers/pull/1673) Adds "How to" guide on using AMS with POROs (@DrSayre)
- [#1730](https://github.com/rails-api/active_model_serializers/pull/1730) Adds documentation for overriding default serializer based on conditions (@groyoh/@cgmckeever)
### [v0.10.0.rc5 (2016-04-04)](https://github.com/rails-api/active_model_serializers/compare/v0.10.0.rc4...v0.10.0.rc5)
Breaking changes:
- [#1645](https://github.com/rails-api/active_model_serializers/pull/1645) Changed :dashed key transform to :dash. (@remear)
- [#1574](https://github.com/rails-api/active_model_serializers/pull/1574) Default key case for the JsonApi adapter changed to dashed. (@remear)
Features:
- [#1645](https://github.com/rails-api/active_model_serializers/pull/1645) Transform keys referenced in values. (@remear)
- [#1650](https://github.com/rails-api/active_model_serializers/pull/1650) Fix serialization scope options `scope`, `scope_name`
take precedence over `serialization_scope` in the controller.
Fix tests that required tearing down dynamic methods. (@bf4)
- [#1644](https://github.com/rails-api/active_model_serializers/pull/1644) Include adapter name in cache key so
that the same serializer can be cached per adapter. (@bf4 via #1346 by @kevintyll)
- [#1642](https://github.com/rails-api/active_model_serializers/pull/1642) Prefer object.cache_key over the generated
cache key. (@bf4 via #1346 by @kevintyll)
- [#1637](https://github.com/rails-api/active_model_serializers/pull/1637) Make references to 'ActionController::Base.cache_store' explicit
in order to avoid issues when application controllers inherit from 'ActionController::API'. (@ncuesta)
- [#1633](https://github.com/rails-api/active_model_serializers/pull/1633) Yield 'serializer' to serializer association blocks. (@bf4)
- [#1616](https://github.com/rails-api/active_model_serializers/pull/1616) SerializableResource handles no serializer like controller. (@bf4)
- [#1618](https://github.com/rails-api/active_model_serializers/issues/1618) Get collection root key for
empty collection from explicit serializer option, when possible. (@bf4)
- [#1574](https://github.com/rails-api/active_model_serializers/pull/1574) Provide key translation. (@remear)
- [#1494](https://github.com/rails-api/active_model_serializers/pull/1494) Make serializers serializalbe
(using the Attributes adapter by default). (@bf4)
- [#1550](https://github.com/rails-api/active_model_serializers/pull/1550) Add
Rails url_helpers to `SerializationContext` for use in links. (@remear, @bf4)
- [#1004](https://github.com/rails-api/active_model_serializers/pull/1004) JSON API errors object implementation.
- Only implements `detail` and `source` as derived from `ActiveModel::Error`
- Provides checklist of remaining questions and remaining parts of the spec.
- [#1515](https://github.com/rails-api/active_model_serializers/pull/1515) Adds support for symbols to the
`ActiveModel::Serializer.type` method. (@groyoh)
- [#1504](https://github.com/rails-api/active_model_serializers/pull/1504) Adds the changes missing from #1454
and add more tests for resource identifier and relationship objects. Fix association block with link
returning `data: nil`.(@groyoh)
- [#1372](https://github.com/rails-api/active_model_serializers/pull/1372) Support
cache_store.read_multi. (@LcpMarvel)
- [#1018](https://github.com/rails-api/active_model_serializers/pull/1018) Add more tests and docs for top-level links. (@leandrocp)
- [#1454](https://github.com/rails-api/active_model_serializers/pull/1454) Add support for
relationship-level links and meta attributes. (@beauby)
- [#1340](https://github.com/rails-api/active_model_serializers/pull/1340) Add support for resource-level meta. (@beauby)
Fixes:
- [#1657](https://github.com/rails-api/active_model_serializers/pull/1657) Add missing missing require "active_support/json". (@andreaseger)
- [#1661](https://github.com/rails-api/active_model_serializers/pull/1661) Fixes `read_attribute_for_serialization` not
seeing methods defined in serialization superclass (#1653, #1658, #1660), introduced in #1650. (@bf4)
- [#1651](https://github.com/rails-api/active_model_serializers/pull/1651) Fix deserialization of nil relationships. (@NullVoxPopuli)
- [#1480](https://github.com/rails-api/active_model_serializers/pull/1480) Fix setting of cache_store from Rails configuration. (@bf4)
Fix unintentional mutating of value in memory cache store. (@groyoh)
- [#1622](https://github.com/rails-api/active_model_serializers/pull/1622) Fragment cache changed from per-record to per-serializer.
Now, two serializers that use the same model may be separately cached. (@lserman)
- [#1478](https://github.com/rails-api/active_model_serializers/pull/1478) Cache store will now be correctly set when serializers are
loaded *before* Rails initializes. (@bf4)
- [#1570](https://github.com/rails-api/active_model_serializers/pull/1570) Fixed pagination issue with last page size. (@bmorrall)
- [#1516](https://github.com/rails-api/active_model_serializers/pull/1516) No longer return a nil href when only
adding meta to a relationship link. (@groyoh)
- [#1458](https://github.com/rails-api/active_model_serializers/pull/1458) Preserve the serializer
type when fragment caching. (@bdmac)
- [#1477](https://github.com/rails-api/active_model_serializers/pull/1477) Fix `fragment_cached?`
method to check if caching. (@bdmac)
- [#1501](https://github.com/rails-api/active_model_serializers/pull/1501) Adds tests for SerializableResource::use_adapter?,doc typos (@domitian)
- [#1488](https://github.com/rails-api/active_model_serializers/pull/1488) Require ActiveSupport's string inflections (@nate00)
Misc:
- [#1608](https://github.com/rails-api/active_model_serializers/pull/1608) Move SerializableResource to ActiveModelSerializers (@groyoh)
- [#1602](https://github.com/rails-api/active_model_serializers/pull/1602) Add output examples to Adapters docs (@remear)
- [#1557](https://github.com/rails-api/active_model_serializers/pull/1557) Update docs regarding overriding the root key (@Jwan622)
- [#1471](https://github.com/rails-api/active_model_serializers/pull/1471) [Cleanup] Serializer caching is its own concern. (@bf4)
- [#1482](https://github.com/rails-api/active_model_serializers/pull/1482) Document JSON API implementation defs and progress in class. (@bf4)
- [#1551](https://github.com/rails-api/active_model_serializers/pull/1551) Added codebeat badge (@korzonek)
- [#1527](https://github.com/rails-api/active_model_serializers/pull/1527) Refactor fragment cache class. (@groyoh)
- [#1560](https://github.com/rails-api/active_model_serializers/pull/1560) Update rubocop and address its warnings. (@bf4 @groyoh)
- [#1545](https://github.com/rails-api/active_model_serializers/pull/1545) Document how to pass arbitrary options to the
serializer (@CodedBeardedSignedTaylor)
- [#1496](https://github.com/rails-api/active_model_serializers/pull/1496) Run all branches against JRuby on CI (@nadavshatz)
- [#1559](https://github.com/rails-api/active_model_serializers/pull/1559) Add a deprecation DSL. (@bf4 @groyoh)
- [#1543](https://github.com/rails-api/active_model_serializers/pull/1543) Add the changes missing from #1535. (@groyoh)
- [#1535](https://github.com/rails-api/active_model_serializers/pull/1535) Move the adapter and adapter folder to
active_model_serializers folder and changes the module namespace. (@domitian @bf4)
- [#1497](https://github.com/rails-api/active_model_serializers/pull/1497) Add JRuby-9000 to appveyor.yml(@corainchicago)
- [#1420](https://github.com/rails-api/active_model_serializers/pull/1420) Adds tests and documentation for polymorphism(@marcgarreau)
### [v0.10.0.rc4 (2016-01-27)](https://github.com/rails-api/active_model_serializers/compare/v0.10.0.rc3...v0.10.0.rc4)
Breaking changes:
- [#1360](https://github.com/rails-api/active_model_serializers/pull/1360)
[#1369](https://github.com/rails-api/active_model_serializers/pull/1369) Drop support for Ruby 1.9.3 (@karaAJC, @maurogeorge)
- [#1131](https://github.com/rails-api/active_model_serializers/pull/1131) Remove Serializer#root_name (@beauby)
- [#1138](https://github.com/rails-api/active_model_serializers/pull/1138) Introduce Adapter::Base (@bf4)
* Adapters now inherit Adapter::Base. 'Adapter' is now a module, no longer a class.
* using a class as a namespace that you also inherit from is complicated and circular at times i.e.
buggy (see https://github.com/rails-api/active_model_serializers/pull/1177)
* The class methods on Adapter aren't necessarily related to the instance methods, they're more
Adapter functions.
* named `Base` because it's a Rails-ism.
* It helps to isolate and highlight what the Adapter interface actually is.
- [#1418](https://github.com/rails-api/active_model_serializers/pull/1418)
serialized collections now use the root option as is; now, only the
root derived from the serializer or object is always pluralized.
Features:
- [#1406](https://github.com/rails-api/active_model_serializers/pull/1406) Allow for custom dynamic values in JSON API links (@beauby)
- [#1270](https://github.com/rails-api/active_model_serializers/pull/1270) Adds `assert_response_schema` test helper (@maurogeorge)
- [#1099](https://github.com/rails-api/active_model_serializers/pull/1099) Adds `assert_serializer` test helper (@maurogeorge)
- [#1403](https://github.com/rails-api/active_model_serializers/pull/1403) Add support for if/unless on attributes/associations (@beauby)
- [#1248](https://github.com/rails-api/active_model_serializers/pull/1248) Experimental: Add support for JSON API deserialization (@beauby)
- [#1378](https://github.com/rails-api/active_model_serializers/pull/1378) Change association blocks
to be evaluated in *serializer* scope, rather than *association* scope. (@bf4)
* Syntax changes from e.g.
`has_many :titles do customers.pluck(:title) end` (in #1356) to
`has_many :titles do object.customers.pluck(:title) end`
- [#1356](https://github.com/rails-api/active_model_serializers/pull/1356) Add inline syntax for
attributes and associations (@bf4 @beauby @noahsilas)
* Allows defining attributes so that they don't conflict with existing methods. e.g. `attribute
:title do 'Mr. Topum Hat' end`
* Allows defining associations so that they don't conflict with existing methods. e.g. `has_many
:titles do customers.pluck(:title) end`
* Allows dynamic associations, as compared to compare to using
[`virtual_value`](https://github.com/rails-api/active_model_serializers/pull/1356#discussion_r47146466).
e.g. `has_many :reviews, virtual_value: [{ id: 1 }, { id: 2 }]`
* Removes dynamically defined methods on the serializer
- [#1336](https://github.com/rails-api/active_model_serializers/pull/1336) Added support for Grape >= 0.13, < 1.0 (@johnhamelink)
- [#1322](https://github.com/rails-api/active_model_serializers/pull/1322) Instrumenting rendering of resources (@bf4, @maurogeorge)
- [#1291](https://github.com/rails-api/active_model_serializers/pull/1291) Add logging (@maurogeorge)
- [#1272](https://github.com/rails-api/active_model_serializers/pull/1272) Add PORO serializable base class: ActiveModelSerializers::Model (@bf4)
- [#1255](https://github.com/rails-api/active_model_serializers/pull/1255) Make more class attributes inheritable (@bf4)
- [#1249](https://github.com/rails-api/active_model_serializers/pull/1249) Inheritance of serializer inheriting the cache configuration(@Rodrigora)
- [#1247](https://github.com/rails-api/active_model_serializers/pull/1247) Add support for toplevel JSON API links (@beauby)
- [#1246](https://github.com/rails-api/active_model_serializers/pull/1246) Add support for resource-level JSON API links (@beauby)
- [#1225](https://github.com/rails-api/active_model_serializers/pull/1225) Better serializer lookup, use nested serializer when it exists (@beauby)
- [#1213](https://github.com/rails-api/active_model_serializers/pull/1213) `type` directive for serializer to control type field with json-api adapter (@youroff)
- [#1172](https://github.com/rails-api/active_model_serializers/pull/1172) Better serializer registration, get more than just the first module (@bf4)
- [#1158](https://github.com/rails-api/active_model_serializers/pull/1158) Add support for wildcards in `include` option (@beauby)
- [#1127](https://github.com/rails-api/active_model_serializers/pull/1127) Add support for nested
associations for JSON and Attributes adapters via the `include` option (@NullVoxPopuli, @beauby).
- [#1050](https://github.com/rails-api/active_model_serializers/pull/1050) Add support for toplevel jsonapi member (@beauby, @bf4)
- [#1251](https://github.com/rails-api/active_model_serializers/pull/1251) Rename ArraySerializer to
CollectionSerializer for clarity, add ActiveModelSerializers.config.collection_serializer (@bf4)
- [#1295](https://github.com/rails-api/active_model_serializers/pull/1295) Add config `serializer_lookup_enabled` that,
when disabled, requires serializers to explicitly specified. (@trek)
Fixes:
- [#1352](https://github.com/rails-api/active_model_serializers/pull/1352) Fix generators; Isolate Rails-specifc code in Railties (@dgynn, @bf4)
- [#1384](https://github.com/rails-api/active_model_serializers/pull/1384)Fix database state leaking across tests (@bf4)
- [#1297](https://github.com/rails-api/active_model_serializers/pull/1297) Fix `fields` option to restrict relationships as well (@beauby)
- [#1239](https://github.com/rails-api/active_model_serializers/pull/1239) Fix duplicates in JSON API compound documents (@beauby)
- [#1214](https://github.com/rails-api/active_model_serializers/pull/1214) retrieve the key from the reflection options when building associations (@NullVoxPopuli, @hut8)
- [#1358](https://github.com/rails-api/active_model_serializers/pull/1358) Handle serializer file paths with spaces (@rwstauner, @bf4)
- [#1195](https://github.com/rails-api/active_model_serializers/pull/1195) Fix id override (@beauby)
- [#1185](https://github.com/rails-api/active_model_serializers/pull/1185) Fix options passing in Json and Attributes adapters (@beauby)
Misc:
- [#1383](https://github.com/rails-api/active_model_serializers/pull/1383) Simplify reflections handling (@beauby)
- [#1370](https://github.com/rails-api/active_model_serializers/pull/1370) Simplify attributes handling via a mixin (@beauby)
- [#1301](https://github.com/rails-api/active_model_serializers/pull/1301) Mapping JSON API spec / schema to AMS (@bf4)
- [#1271](https://github.com/rails-api/active_model_serializers/pull/1271) Handle no serializer source file to digest (@bf4)
- [#1260](https://github.com/rails-api/active_model_serializers/pull/1260) Serialization and Cache Documentation (@bf4)
- [#1259](https://github.com/rails-api/active_model_serializers/pull/1259) Add more info to CONTRIBUTING (@bf4)
- [#1233](https://github.com/rails-api/active_model_serializers/pull/1233) Top-level meta and meta_key options no longer handled at serializer level (@beauby)
- [#1232](https://github.com/rails-api/active_model_serializers/pull/1232) fields option no longer handled at serializer level (@beauby)
- [#1220](https://github.com/rails-api/active_model_serializers/pull/1220) Remove empty rubocop.rake (@maurogeorge)
- [#1178](https://github.com/rails-api/active_model_serializers/pull/1178) env CAPTURE_STDERR=false lets devs see hard failures (@bf4)
- [#1177](https://github.com/rails-api/active_model_serializers/pull/1177) Remove Adapter autoloads in favor of require (@bf4)
- [#1117](https://github.com/rails-api/active_model_serializers/pull/1117) FlattenJson adapter no longer inherits Json adapter, renamed to Attributes (@bf4)
- [#1171](https://github.com/rails-api/active_model_serializers/pull/1171) add require statements to top of file (@shicholas)
- [#1167](https://github.com/rails-api/active_model_serializers/pull/1167) Delegate Serializer.attributes to Serializer.attribute (@bf4)
- [#1174](https://github.com/rails-api/active_model_serializers/pull/1174) Consistently refer to the 'JSON API' and the 'JsonApi' adapter (@bf4)
- [#1173](https://github.com/rails-api/active_model_serializers/pull/1173) Comment private accessor warnings (@bf4)
- [#1166](https://github.com/rails-api/active_model_serializers/pull/1166) Prefer methods over instance variables (@bf4)
- [#1168](https://github.com/rails-api/active_model_serializers/pull/1168) Fix appveyor failure cache not being expired (@bf4)
- [#1161](https://github.com/rails-api/active_model_serializers/pull/1161) Remove duplicate test helper (@bf4)
- [#1360](https://github.com/rails-api/active_model_serializers/pull/1360) Update CI to test 2.2.2 -> 2.2.3 (@karaAJC)
- [#1371](https://github.com/rails-api/active_model_serializers/pull/1371) Refactor, update, create documentation (@bf4)
### [v0.10.0.rc3 (2015-09-16)](https://github.com/rails-api/active_model_serializers/compare/v0.10.0.rc2...v0.10.0.rc3)
- [#1129](https://github.com/rails-api/active_model_serializers/pull/1129) Remove SerializableResource.serialize in favor of `.new` (@bf4)
- [#1155](https://github.com/rails-api/active_model_serializers/pull/1155) Outside controller use tutorial (@CodedBeardedSignedTaylor)
- [#1154](https://github.com/rails-api/active_model_serializers/pull/1154) Rubocop fixes for issues introduced by #1089 (@NullVoxPopuli)
- [#1089](https://github.com/rails-api/active_model_serializers/pull/1089) Add ActiveModelSerializers.logger with default null device (@bf4)
- [#1109](https://github.com/rails-api/active_model_serializers/pull/1109) Make better use of Minitest's lifecycle (@bf4)
- [#1144](https://github.com/rails-api/active_model_serializers/pull/1144) Fix Markdown to adapters documentation (@bacarini)
- [#1121](https://github.com/rails-api/active_model_serializers/pull/1121) Refactor `add_links` in JSONAPI adapter. (@beauby)
- [#1150](https://github.com/rails-api/active_model_serializers/pull/1150) Remove legacy method accidentally reintroduced in #1017 (@beauby)
- [#1149](https://github.com/rails-api/active_model_serializers/pull/1149) Update README with nested included association example. (@mattmueller)
- [#1110](https://github.com/rails-api/active_model_serializers/pull/1110) Add lint tests for AR models (@beauby)
- [#1131](https://github.com/rails-api/active_model_serializers/pull/1131) Extended format for JSONAPI `include` option (@beauby)
* adds extended format for `include` option to JsonApi adapter
- [#1142](https://github.com/rails-api/active_model_serializers/pull/1142) Updating wording on cache expiry in README (@leighhalliday)
- [#1140](https://github.com/rails-api/active_model_serializers/pull/1140) Fix typo in fieldset exception (@lautis)
- [#1132](https://github.com/rails-api/active_model_serializers/pull/1132) Get rid of unnecessary instance variables, and implied dependencies. (@beauby)
- [#1139](https://github.com/rails-api/active_model_serializers/pull/1139) Documentation for serializing resources without render (@PericlesTheo)
- [#1017](https://github.com/rails-api/active_model_serializers/pull/1017) Make Adapters registerable so they are not namespace-constrained (@bf4)
- [#1120](https://github.com/rails-api/active_model_serializers/pull/1120) Add windows platform to loading sqlite3 (@Eric-Guo)
- [#1123](https://github.com/rails-api/active_model_serializers/pull/1123) Remove url options (@bacarini)
- [#1093](https://github.com/rails-api/active_model_serializers/pull/1093) Factor `with_adapter` + force cache clear before each test. (@beauby)
- [#1095](https://github.com/rails-api/active_model_serializers/pull/1095) Add documentation about configuration options. (@beauby)
- [#1069](https://github.com/rails-api/active_model_serializers/pull/1069) Add test coverage; account for no artifacts on CI (@bf4)
- [#1103](https://github.com/rails-api/active_model_serializers/pull/1103) Move `id` and `json_api_type` methods from `Serializer` to `JsonApi`. (@beauby)
- [#1106](https://github.com/rails-api/active_model_serializers/pull/1106) Add Style enforcer (via Rubocop) (@bf4)
- [#1079](https://github.com/rails-api/active_model_serializers/pull/1079) Add ArraySerializer#object like Serializer (@bf4)
- [#1096](https://github.com/rails-api/active_model_serializers/pull/1096) Fix definition of serializer attributes with multiple calls to `attri… (@beauby)
- [#1105](https://github.com/rails-api/active_model_serializers/pull/1105) Add ActiveRecord-backed fixtures. (@beauby)
- [#1108](https://github.com/rails-api/active_model_serializers/pull/1108) Better lint (@bf4)
- [#1102](https://github.com/rails-api/active_model_serializers/pull/1102) Remove remains of `embed` option. (@beauby)
- [#1090](https://github.com/rails-api/active_model_serializers/pull/1090) Clarify AMS dependencies (@bf4)
- [#1081](https://github.com/rails-api/active_model_serializers/pull/1081) Add configuration option to set resource type to singular/plural (@beauby)
- [#1067](https://github.com/rails-api/active_model_serializers/pull/1067) Fix warnings (@bf4)
- [#1066](https://github.com/rails-api/active_model_serializers/pull/1066) Adding appveyor to the project (@joaomdmoura, @Eric-Guo, @bf4)
- [#1071](https://github.com/rails-api/active_model_serializers/pull/1071) Make testing suite running and pass in Windows (@Eric-Guo, @bf4)
- [#1041](https://github.com/rails-api/active_model_serializers/pull/1041) Adding pagination links (@bacarini)
* adds support for `pagination links` at top level of JsonApi adapter
- [#1063](https://github.com/rails-api/active_model_serializers/pull/1063) Lead by example: lint PORO model (@bf4)
- [#1](https://github.com/rails-api/active_model_serializers/pull/1) Test caller line parsing and digesting (@bf4)
- [#1048](https://github.com/rails-api/active_model_serializers/pull/1048) Let FlattenJson adapter decide it doesn't include meta (@bf4)
- [#1060](https://github.com/rails-api/active_model_serializers/pull/1060) Update fragment cache to support namespaced objects (@aaronlerch)
- [#1052](https://github.com/rails-api/active_model_serializers/pull/1052) Use underscored json_root when serializing a collection (@whatthewhat)
- [#1051](https://github.com/rails-api/active_model_serializers/pull/1051) Fix some invalid JSON in docs (@tjschuck)
- [#1049](https://github.com/rails-api/active_model_serializers/pull/1049) Fix incorrect s/options = {}/options ||= {} (@bf4)
- [#1037](https://github.com/rails-api/active_model_serializers/pull/1037) allow for type attribute (@lanej)
- [#1034](https://github.com/rails-api/active_model_serializers/pull/1034) allow id attribute to be overriden (@lanej)
- [#1035](https://github.com/rails-api/active_model_serializers/pull/1035) Fixed Comments highlight (@artLopez)
- [#1031](https://github.com/rails-api/active_model_serializers/pull/1031) Disallow to define multiple associations at once (@bolshakov)
- [#1032](https://github.com/rails-api/active_model_serializers/pull/1032) Wrap railtie requirement with rescue (@elliotlarson)
- [#1026](https://github.com/rails-api/active_model_serializers/pull/1026) Bump Version Number to 0.10.0.rc2 (@jfelchner)
- [#985](https://github.com/rails-api/active_model_serializers/pull/985) Associations implementation refactoring (@bolshakov)
- [#954](https://github.com/rails-api/active_model_serializers/pull/954) Encapsulate serialization in ActiveModel::SerializableResource (@bf4)
- [#972](https://github.com/rails-api/active_model_serializers/pull/972) Capture app warnings on test run (@bf4)
- [#1019](https://github.com/rails-api/active_model_serializers/pull/1019) Improve README.md (@baojjeu)
- [#998](https://github.com/rails-api/active_model_serializers/pull/998) Changing root to model class name (@joaomdmoura)
- [#1006](https://github.com/rails-api/active_model_serializers/pull/1006) Fix adapter inflection bug for api -> API (@bf4)
- [#1016](https://github.com/rails-api/active_model_serializers/pull/1016) require rails/railtie before subclassing Rails::Railtie (@bf4)
- [#1013](https://github.com/rails-api/active_model_serializers/pull/1013) Root option with empty array support (@vyrak, @mareczek)
- [#994](https://github.com/rails-api/active_model_serializers/pull/994) Starting Docs structure (@joaomdmoura)
- [#1007](https://github.com/rails-api/active_model_serializers/pull/1007) Bug fix for ArraySerializer json_key (@jiajiawang)
- [#1003](https://github.com/rails-api/active_model_serializers/pull/1003) Fix transient test failures (@Rodrigora)
- [#996](https://github.com/rails-api/active_model_serializers/pull/996) Add linter for serializable resource (@bf4)
- [#990](https://github.com/rails-api/active_model_serializers/pull/990) Adding json-api meta test (@joaomdmoura)
- [#984](https://github.com/rails-api/active_model_serializers/pull/984) Add option "key" to serializer associations (@Rodrigora)
- [#982](https://github.com/rails-api/active_model_serializers/pull/982) Fix typo (@bf4)
- [#981](https://github.com/rails-api/active_model_serializers/pull/981) Remove unused PORO#to_param (@bf4)
- [#978](https://github.com/rails-api/active_model_serializers/pull/978) fix generators template bug (@regonn)
- [#975](https://github.com/rails-api/active_model_serializers/pull/975) Fixes virtual value not being used (@GriffinHeart)
- [#970](https://github.com/rails-api/active_model_serializers/pull/970) Fix transient tests failures (@Rodrigora)
- [#962](https://github.com/rails-api/active_model_serializers/pull/962) Rendering objects that doesn't have serializers (@bf4, @joaomdmoura, @JustinAiken)
- [#939](https://github.com/rails-api/active_model_serializers/pull/939) Use a more precise generated cache key (@aaronlerch)
- [#971](https://github.com/rails-api/active_model_serializers/pull/971) Restore has_one to generator (@bf4)
- [#965](https://github.com/rails-api/active_model_serializers/pull/965) options fedault valueserializable_hash and as_json (@bf4)
- [#959](https://github.com/rails-api/active_model_serializers/pull/959) TYPO on README.md (@kangkyu)
### [v0.10.0.rc2 (2015-06-16)](https://github.com/rails-api/active_model_serializers/compare/v0.10.0.rc1...v0.10.0.rc2)
- [#958](https://github.com/rails-api/active_model_serializers/pull/958) Splitting json adapter into two (@joaomdmoura)
* adds FlattenJSON as default adapter
- [#953](https://github.com/rails-api/active_model_serializers/pull/953) use model name to determine the type (@lsylvester)
* uses model name to determine the type
- [#949](https://github.com/rails-api/active_model_serializers/pull/949) Don't pass serializer option to associated serializers (@bf4, @edwardloveall)
- [#902](https://github.com/rails-api/active_model_serializers/pull/902) Added serializer file digest to the cache_key (@cristianbica)
- [#948](https://github.com/rails-api/active_model_serializers/pull/948) AMS supports JSONAPI 1.0 instead of RC4 (@SeyZ)
- [#936](https://github.com/rails-api/active_model_serializers/pull/936) Include meta when using json adapter with custom root (@chrisbranson)
- [#942](https://github.com/rails-api/active_model_serializers/pull/942) Small code styling issue (@thiagofm)
- [#930](https://github.com/rails-api/active_model_serializers/pull/930) Reverting PR #909 (@joaomdmoura)
- [#924](https://github.com/rails-api/active_model_serializers/pull/924) Avoid unnecessary calls to attribute methods when fragment caching (@navinpeiris)
- [#925](https://github.com/rails-api/active_model_serializers/pull/925) Updates JSON API Adapter to generate RC4 schema (@benedikt)
* adds JSON API support 1.0
- [#918](https://github.com/rails-api/active_model_serializers/pull/918) Adding rescue_with_handler to clear state (@ryansch)
- [#909](https://github.com/rails-api/active_model_serializers/pull/909) Defining Json-API Adapter as Default (@joaomdmoura)
* remove root key option and split JSON adapter
- [#914](https://github.com/rails-api/active_model_serializers/pull/914) Prevent possible duplicated attributes in serializer (@groyoh)
- [#880](https://github.com/rails-api/active_model_serializers/pull/880) Inabling subclasses serializers to inherit attributes (@groyoh)
- [#913](https://github.com/rails-api/active_model_serializers/pull/913) Avoiding the serializer option when instantiating a new one for ArraySerializer Fixed #911 (@groyoh)
- [#897](https://github.com/rails-api/active_model_serializers/pull/897) Allow to define custom serializer for given class (@imanel)
- [#892](https://github.com/rails-api/active_model_serializers/pull/892) Fixed a bug that appeared when json adapter serialize a nil association (@groyoh)
- [#895](https://github.com/rails-api/active_model_serializers/pull/895) Adding a test to cover 'meta' and 'meta_key' attr_readers (@adomokos)
- [#894](https://github.com/rails-api/active_model_serializers/pull/894) Fixing typos in README.md (@adomokos)
- [#888](https://github.com/rails-api/active_model_serializers/pull/888) Changed duplicated test name in action controller test (@groyoh)
- [#890](https://github.com/rails-api/active_model_serializers/pull/890) Remove unused method `def_serializer` (@JustinAiken)
- [#887](https://github.com/rails-api/active_model_serializers/pull/887) Fixing tests on JRuby (@joaomdmoura)
- [#885](https://github.com/rails-api/active_model_serializers/pull/885) Updates rails versions for test and dev (@tonyta)
### [v0.10.0.rc1 (2015-04-22)](https://github.com/rails-api/active_model_serializers/compare/86fc7d7227f3ce538fcb28c1e8c7069ce311f0e1...v0.10.0.rc1)
- [#810](https://github.com/rails-api/active_model_serializers/pull/810) Adding Fragment Cache to AMS (@joaomdmoura)
* adds fragment cache support
- [#868](https://github.com/rails-api/active_model_serializers/pull/868) Fixed a bug that appears when a nil association is included (@groyoh)
- [#861](https://github.com/rails-api/active_model_serializers/pull/861) README: Add emphasis to single-word difference (@machty)
- [#858](https://github.com/rails-api/active_model_serializers/pull/858) Included resource fixes (@mateomurphy)
- [#853](https://github.com/rails-api/active_model_serializers/pull/853) RC3 Updates for JSON API (@mateomurphy)
- [#852](https://github.com/rails-api/active_model_serializers/pull/852) Fix options merge order in `each_association` (@mateomurphy)
- [#850](https://github.com/rails-api/active_model_serializers/pull/850) Use association value for determining serializer used (@mateomurphy)
- [#843](https://github.com/rails-api/active_model_serializers/pull/843) Remove the mailing list from the README (@JoshSmith)
- [#842](https://github.com/rails-api/active_model_serializers/pull/842) Add notes on how you can help to contributing documentation (@JoshSmith)
- [#833](https://github.com/rails-api/active_model_serializers/pull/833) Cache serializers for class (@lsylvester)
- [#837](https://github.com/rails-api/active_model_serializers/pull/837) Store options in array serializers (@kurko)
- [#836](https://github.com/rails-api/active_model_serializers/pull/836) Makes passed in options accessible inside serializers (@kurko)
- [#773](https://github.com/rails-api/active_model_serializers/pull/773) Make json api adapter 'include' option accept an array (@sweatypitts)
- [#830](https://github.com/rails-api/active_model_serializers/pull/830) Add contributing readme (@JoshSmith)
- [#811](https://github.com/rails-api/active_model_serializers/pull/811) Reimplement serialization scope and scope_name (@mateomurphy)
- [#725](https://github.com/rails-api/active_model_serializers/pull/725) Support has_one to be compatible with 0.8.x (@ggordon)
* adds `has_one` attribute for backwards compatibility
- [#822](https://github.com/rails-api/active_model_serializers/pull/822) Replace has_one with attribute in template (@bf4)
- [#821](https://github.com/rails-api/active_model_serializers/pull/821) Fix explicit serializer for associations (@wjordan)
- [#798](https://github.com/rails-api/active_model_serializers/pull/798) Fix lost test `test_include_multiple_posts_and_linked` (@donbobka)
- [#807](https://github.com/rails-api/active_model_serializers/pull/807) Add Overriding attribute methods section to README. (@alexstophel)
- [#693](https://github.com/rails-api/active_model_serializers/pull/693) Cache Support at AMS 0.10.0 (@joaomdmoura)
* adds cache support to attributes and associations.
- [#792](https://github.com/rails-api/active_model_serializers/pull/792) Association overrides (@kurko)
* adds method to override association
- [#794](https://github.com/rails-api/active_model_serializers/pull/794) add to_param for correct URL generation (@carlesjove)
### v0.10.0-pre
- [Introduce Adapter](https://github.com/rails-api/active_model_serializers/commit/f00fe5595ddf741dc26127ed8fe81adad833ead5)
- Prefer `ActiveModel::Serializer` to `ActiveModelSerializers`:
- [Namespace](https://github.com/rails-api/active_model_serializers/commit/729a823868e8c7ac86c653fcc7100ee511e08cb6#diff-fe7aa2941c19a41ccea6e52940d84016).
- [README](https://github.com/rails-api/active_model_serializers/commit/4a2d9853ba7486acc1747752982aa5650e7fd6e9).

15
CHANGELOG-prehistory.md Normal file
View File

@ -0,0 +1,15 @@
## Prehistory
- [Changing Serialization/Serializers namespace to `Serializable` (November 30, 2011)](https://github.com/rails/rails/commit/8896b4fdc8a543157cdf4dfc378607ebf6c10ab0)
- [Merge branch 'serializers'. This implements the ActiveModel::Serializer object. Includes code, tests, generators and guides. From José and Yehuda with love.](https://github.com/rails/rails/commit/fcacc6986ab60f1fb2e423a73bf47c7abd7b191d)
- But [was reverted](https://github.com/rails/rails/commit/5b2eb64ceb08cd005dc06b721935de5853971473).
'[Revert the serializers API as other alternatives are now also under discussion](https://github.com/rails/rails/commit/0a4035b12a6c59253cb60f9e3456513c6a6a9d33)'.
- [Proposed Implementation to Rails 3.2 by @wycats and @josevalim (November 25, 2011)](https://github.com/rails/rails/pull/3753)
- [Creation of `ActionController::Serialization`, initial serializer
support (September, 26 2011)](https://github.com/rails/rails/commit/8ff7693a8dc61f43fc4eaf72ed24d3b8699191fe).
- [Docs and CHANGELOG](https://github.com/rails/rails/commit/696d01f7f4a8ed787924a41cce6df836cd73c46f)
- [Deprecation of ActiveModel::Serialization to ActiveModel::Serializable](https://github.com/rails/rails/blob/696d01f7f4a8ed787924a41cce6df836cd73c46f/activemodel/lib/active_model/serialization.rb)
- [Creation of `ActiveModel::Serialization` from `ActiveModel::Serializer` in Rails (2009)](https://github.com/rails/rails/commit/c6bc8e662614be711f45a8d4b231d5f993b024a7#diff-d029b9768d8df0407a35804a468e3ae5)
- [Integration of `ActiveModel::Serializer` into `ActiveRecord::Serialization`](https://github.com/rails/rails/commit/783db25e0c640c1588732967a87d65c10fddc08e)
- [Creation of `ActiveModel::Serializer` in Rails (2009)](https://github.com/rails/rails/commit/d2b78b3594b9cc9870e6a6ebfeb2e56d00e6ddb8#diff-80d5beeced9bdc24ca2b04a201543bdd)
- [Creation of `ActiveModel::Serializers::JSON` in Rails (2009)](https://github.com/rails/rails/commit/fbdf706fffbfb17731a1f459203d242414ef5086)

View File

@ -1,200 +1,19 @@
## 0.09.x
## Dev
### [0-9-stable](https://github.com/rails-api/active_model_serializers/compare/v0.9.8...0-9-stable)
### [master (unreleased)](https://github.com/rails-api/active_model_serializers/compare/master..dev)
### [v0.9.8 (2020-12-10)](https://github.com/rails-api/active_model_serializers/compare/v0.9.7...v0.9.8)
- [#2373](https://github.com/rails-api/active_model_serializers/pull/2373) Fix Rails 6.0 deprecation warnings. (@supremebeing7)
### [v0.9.7 (2017-05-01)](https://github.com/rails-api/active_model_serializers/compare/v0.9.6...v0.9.7)
- [#2080](https://github.com/rails-api/active_model_serializers/pull/2080) remove `{ payload: nil }` from `!serialize.active_model_serializers` ActiveSupport::Notification. `payload` never had a value. Changes, for example `{ serializer: 'ActiveModel::DefaultSerializer', payload: nil }` to be `{ serializer: 'ActiveModel::DefaultSerializer' }` (@yosiat)
### [v0.9.6 (2017-01-10)](https://github.com/rails-api/active_model_serializers/compare/v0.9.5...v0.9.6)
- [#2008](https://github.com/rails-api/active_model_serializers/pull/2008) Fix warning on Thor. (@kirs)
### [v0.9.5 (2016-03-30)](https://github.com/rails-api/active_model_serializers/compare/v0.9.4...v0.9.5)
- [#1607](https://github.com/rails-api/active_model_serializers/pull/1607) Merge multiple nested associations. (@Hirtenknogger)
### [v0.9.4 (2016-01-05)](https://github.com/rails-api/active_model_serializers/compare/v0.9.3...v0.9.4)
- [#752](https://github.com/rails-api/active_model_serializers/pull/752) Tiny improvement of README 0-9-stable (@basiam)
- [#749](https://github.com/rails-api/active_model_serializers/pull/749) remove trailing whitespace (@shwoodard)
- [#717](https://github.com/rails-api/active_model_serializers/pull/717) fixed issue with rendering Hash which appears in rails 4.2.0.beta4 (@kurko, @greshny)
- [#790](https://github.com/rails-api/active_model_serializers/pull/790) pass context to ArraySerializer (@lanej)
- [#797](https://github.com/rails-api/active_model_serializers/pull/797) Fix and test for #490 (@afn)
- [#813](https://github.com/rails-api/active_model_serializers/pull/813) Allow to define custom serializer for given class (@jtomaszewski)
- [#841](https://github.com/rails-api/active_model_serializers/pull/841) Fix issue with embedding multiple associations under the same root key (@antstorm)
- [#748](https://github.com/rails-api/active_model_serializers/pull/748) Propagate serialization_options across associations (@raphaelpereira)
### [v0.9.3 (2015/01/21 20:29 +00:00)](https://github.com/rails-api/active_model_serializers/compare/v0.9.2...v0.9.3)
Breaking changes:
Features:
- [#774](https://github.com/rails-api/active_model_serializers/pull/774) Fix nested include attributes (@nhocki)
- [#771](https://github.com/rails-api/active_model_serializers/pull/771) Make linked resource type names consistent with root names (@sweatypitts)
- [#696](https://github.com/rails-api/active_model_serializers/pull/696) Explicitly set serializer for associations (@ggordon)
- [#700](https://github.com/rails-api/active_model_serializers/pull/700) sparse fieldsets (@arenoir)
- [#768](https://github.com/rails-api/active_model_serializers/pull/768) Adds support for `meta` and `meta_key` attribute (@kurko)
### [v0.9.2](https://github.com/rails-api/active_model_serializers/compare/v0.9.1...v0.9.2)
Fixes:
### [v0.9.1 (2014/12/04 11:54 +00:00)](https://github.com/rails-api/active_model_serializers/compare/v0.9.0...v0.9.1)
Misc:
- [#707](https://github.com/rails-api/active_model_serializers/pull/707) A Friendly Note on Which AMS Version to Use (@jherdman)
- [#730](https://github.com/rails-api/active_model_serializers/pull/730) Fixes nested has_many links in JSONAPI (@kurko)
- [#718](https://github.com/rails-api/active_model_serializers/pull/718) Allow overriding the adapter with render option (@ggordon)
- [#720](https://github.com/rails-api/active_model_serializers/pull/720) Rename attribute with :key (0.8.x compatibility) (@ggordon)
- [#728](https://github.com/rails-api/active_model_serializers/pull/728) Use type as key for linked resources (@kurko)
- [#729](https://github.com/rails-api/active_model_serializers/pull/729) Use the new beta build env on Travis (@joshk)
- [#703](https://github.com/rails-api/active_model_serializers/pull/703) Support serializer and each_serializer options in renderer (@ggordon, @mieko)
- [#727](https://github.com/rails-api/active_model_serializers/pull/727) Includes links inside of linked resources (@kurko)
- [#726](https://github.com/rails-api/active_model_serializers/pull/726) Bugfix: include nested has_many associations (@kurko)
- [#722](https://github.com/rails-api/active_model_serializers/pull/722) Fix infinite recursion (@ggordon)
- [#1](https://github.com/rails-api/active_model_serializers/pull/1) Allow for the implicit use of ArraySerializer when :each_serializer is specified (@mieko)
- [#692](https://github.com/rails-api/active_model_serializers/pull/692) Include 'linked' member for json-api collections (@ggordon)
- [#714](https://github.com/rails-api/active_model_serializers/pull/714) Define as_json instead of to_json (@guilleiguaran)
- [#710](https://github.com/rails-api/active_model_serializers/pull/710) JSON-API: Don't include linked section if associations are empty (@guilleiguaran)
- [#711](https://github.com/rails-api/active_model_serializers/pull/711) Fixes rbx gems bundling on TravisCI (@kurko)
- [#709](https://github.com/rails-api/active_model_serializers/pull/709) Add type key when association name is different than object type (@guilleiguaran)
- [#708](https://github.com/rails-api/active_model_serializers/pull/708) Handle correctly null associations (@guilleiguaran)
- [#691](https://github.com/rails-api/active_model_serializers/pull/691) Fix embed option for associations (@jacob-s-son)
- [#689](https://github.com/rails-api/active_model_serializers/pull/689) Fix support for custom root in JSON-API adapter (@guilleiguaran)
- [#685](https://github.com/rails-api/active_model_serializers/pull/685) Serialize ids as strings in JSON-API adapter (@guilleiguaran)
- [#684](https://github.com/rails-api/active_model_serializers/pull/684) Refactor adapters to implement support for array serialization (@guilleiguaran)
- [#682](https://github.com/rails-api/active_model_serializers/pull/682) Include root by default in JSON-API serializers (@guilleiguaran)
- [#625](https://github.com/rails-api/active_model_serializers/pull/625) Add DSL for urls (@JordanFaust)
- [#677](https://github.com/rails-api/active_model_serializers/pull/677) Add support for embed: :ids option for in associations (@guilleiguaran)
- [#681](https://github.com/rails-api/active_model_serializers/pull/681) Check superclasses for Serializers (@quainjn)
- [#680](https://github.com/rails-api/active_model_serializers/pull/680) Add support for root keys (@NullVoxPopuli)
- [#675](https://github.com/rails-api/active_model_serializers/pull/675) Support Rails 4.2.0 (@tricknotes)
- [#667](https://github.com/rails-api/active_model_serializers/pull/667) Require only activemodel instead of full rails (@guilleiguaran)
- [#653](https://github.com/rails-api/active_model_serializers/pull/653) Add "_test" suffix to JsonApi::HasManyTest filename. (@alexgenco)
- [#631](https://github.com/rails-api/active_model_serializers/pull/631) Update build badge URL (@craiglittle)
## [0.10.x](CHANGELOG-0-10.md)
### [v0.9.0](https://github.com/rails-api/active_model_serializers/compare/v0.9.0.alpha1...v0.9.0)
## [0.09.x](CHANGELOG-0-09.md)
### [0.9.0.alpha1 - January 7, 2014](https://github.com/rails-api/active_model_serializers/compare/d72b66d4c...v0.9.0.alpha1)
## [0.08.x](CHANGELOG-0-08.md)
### 0.9.0.pre
* The following methods were removed
- Model#active\_model\_serializer
- Serializer#include!
- Serializer#include?
- Serializer#attr\_disabled=
- Serializer#cache
- Serializer#perform\_caching
- Serializer#schema (needs more discussion)
- Serializer#attribute
- Serializer#include\_#{name}? (filter method added)
- Serializer#attributes (took a hash)
* The following things were added
- Serializer#filter method
- CONFIG object
* Remove support for ruby 1.8 versions.
* Require rails >= 3.2.
* Serializers for associations are being looked up in a parent serializer's namespace first. Same with controllers' namespaces.
* Added a "prefix" option in case you want to use a different version of serializer.
* Serializers default namespace can be set in `default_serializer_options` and inherited by associations.
# VERSION 0.9.0.pre
* The following methods were removed
- Model#active\_model\_serializer
- Serializer#include!
- Serializer#include?
- Serializer#attr\_disabled=
- Serializer#cache
- Serializer#perform\_caching
- Serializer#schema (needs more discussion)
- Serializer#attribute
- Serializer#include\_#{name}? (filter method added)
- Serializer#attributes (took a hash)
* The following things were added
- Serializer#filter method
- CONFIG object
* Remove support for ruby 1.8 versions.
* Require rails >= 3.2.
* Serializers for associations are being looked up in a parent serializer's namespace first. Same with controllers' namespaces.
* Added a "prefix" option in case you want to use a different version of serializer.
* Serializers default namespace can be set in `default_serializer_options` and inherited by associations.
# VERSION 0.8.1
* Fix bug whereby a serializer using 'options' would blow up.
# VERSION 0.8.0
* Attributes can now have optional types.
* A new DefaultSerializer ensures that POROs behave the same way as ActiveModels.
* If you wish to override ActiveRecord::Base#to\_Json, you can now require
'active\_record/serializer\_override'. We don't recommend you do this, but
many users do, so we've left it optional.
* Fixed a bug where ActionController wouldn't always have MimeResponds.
* An optional caching feature allows you to cache JSON & hashes that AMS uses.
Adding 'cached true' to your Serializers will turn on this cache.
* URL helpers used inside of Engines now work properly.
* Serializers now can filter attributes with `only` and `except`:
```
UserSerializer.new(user, only: [:first_name, :last_name])
UserSerializer.new(user, except: :first_name)
```
* Basic Mongoid support. We now include our mixins in the right place.
* On Ruby 1.8, we now generate an `id` method that properly serializes `id`
columns. See issue #127 for more.
* Add an alias for `scope` method to be the name of the context. By default
this is `current_user`. The name is automatically set when using
`serialization_scope` in the controller.
* Pass through serialization options (such as `:include`) when a model
has no serializer defined.
# VERSION 0.7.0
* ```embed_key``` option to allow embedding by attributes other than IDs
* Fix rendering nil with custom serializer
* Fix global ```self.root = false```
* Add support for specifying the serializer for an association as a String
* Able to specify keys on the attributes method
* Serializer Reloading via ActiveSupport::DescendantsTracker
* Reduce double map to once; Fixes datamapper eager loading.
# VERSION 0.6.0
* Serialize sets properly
* Add root option to ArraySerializer
* Support polymorphic associations
* Support :each_serializer in ArraySerializer
* Add `scope` method to easily access the scope in the serializer
* Fix regression with Rails 3.2.6; add Rails 4 support
* Allow serialization_scope to be disabled with serialization_scope nil
* Array serializer should support pure ruby objects besides serializers
# VERSION 0.5.0
* First tagged version
* Changes generators to always generate an ApplicationSerializer
## [Prehistory](CHANGELOG-prehistory.md)

74
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,74 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and
orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting one of the owners listed at https://rubygems.org/gems/active_model_serializers. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

View File

@ -1,20 +1,100 @@
Contributing to AMS
===================
## Have an issue?
First of all, **thank you**!
Before opening an issue, try the following:
Now, for the details:
##### Consult the documentation
Please file issues on the [GitHub Issues
list](https://github.com/rails-api/active_model_serializers/issues).
See if your issue can be resolved by information in the [documentation](README.md).
Please discuss new features or ask for feedback about a new feature [on
rails-api-core](https://groups.google.com/forum/#!forum/rails-api-core).
##### Check for an existing issue
If you want a feature implemented, the best way to get it done is to submit a
pull request that implements it. Tests and docs would be nice.
Take a look at the issues to see if a similar one has already been created. If
one exists, please add any additional information that might expedite
resolution.
Please include a CHANGELOG with all entries that change behavior.
#### Open an issue
:heart: :sparkling_heart: :heart:
If the documentation wasn't able to help resolve the issue and no issue already
exists, please open a new issue with the following in mind:
- Please make sure only to include one issue per report. If you encounter
multiple, unrelated issues, please report them as such.
- Be detailed. Provide backtraces and example code when possible. Provide
information about your environment. e.g., Ruby version, rails version, etc.
- Own your issue. Actively participate in the discussion and help drive the
issue to closure.
- If you resolve your own issue, please share the details on the issue and close
it out. Others might have the same issue and sharing solutions is helpful.
## Contributing
Contributing can be done in many ways and is not exclusive to code. If you have
thoughts on a particular issue or feature, we encourage you to open new issues
for discussion or add your comments to existing ones.
#### Pull requests
We also gladly welcome pull requests. When preparing to work on pull request,
please adhere to these standards:
- Base work on the relevant branch:
[0.10-stable](https://github.com/rails-api/active_model_serializers/tree/0-10-stable)
or
[0.9-stable](https://github.com/rails-api/active_model_serializers/tree/0-9-stable)
or
[0.8-stable](https://github.com/rails-api/active_model_serializers/tree/0-8-stable)
- Squash your commits and regularly rebase off master.
- Provide a description of the changes contained in the pull request.
- Note any specific areas that should be reviewed.
- Include tests.
- The test suite must pass on [supported Ruby versions](.travis.yml)
- Include updates to the [documentation](docs)
where applicable.
- Update the
[CHANGELOG](CHANGELOG.md)
to the appropriate sections with a brief description of the changes.
- Do not change the VERSION file.
#### Running tests
Run all tests
`$ rake test`
Run a single test suite
`$ rake test TEST=path/to/test.rb`
Run a single test
`$ rake test TEST=path/to/test.rb TESTOPTS="--name=test_something"`
Run tests against different Rails versions by setting the RAILS_VERSION variable
and bundling gems. (save this script somewhere executable and run from top of AMS repository)
```bash
#!/usr/bin/env bash
rcommand='puts YAML.load_file("./.travis.yml")["env"]["matrix"].join(" ").gsub("RAILS_VERSION=", "")'
versions=$(ruby -ryaml -e "$rcommand")
for version in ${versions[@]}; do
export RAILS_VERSION="$version"
rm -f Gemfile.lock
bundle check || bundle --local || bundle
bundle exec rake test
if [ "$?" -eq 0 ]; then
# green in ANSI
echo -e "\033[32m **** Tests passed against Rails ${RAILS_VERSION} **** \033[0m"
else
# red in ANSI
echo -e "\033[31m **** Tests failed against Rails ${RAILS_VERSION} **** \033[0m"
read -p '[Enter] any key to continue, [q] to quit...' prompt
if [ "$prompt" = 'q' ]; then
unset RAILS_VERSION
exit 1
fi
fi
unset RAILS_VERSION
done
```

View File

@ -1,586 +0,0 @@
<strong>This was the original design document for serializers.</strong> It is useful mostly for historical purposes as the public API has changed.
h2. Rails Serializers
This guide describes how to use Active Model serializers to build non-trivial JSON services in Rails. By reading this guide, you will learn:
* When to use the built-in Active Model serialization
* When to use a custom serializer for your models
* How to use serializers to encapsulate authorization concerns
* How to create serializer templates to describe the application-wide structure of your serialized JSON
* How to build resources not backed by a single database table for use with JSON services
This guide covers an intermediate topic and assumes familiarity with Rails conventions. It is suitable for applications that expose a
JSON API that may return different results based on the authorization status of the user.
h3. Serialization
By default, Active Record objects can serialize themselves into JSON by using the `to_json` method. This method takes a series of additional
parameter to control which properties and associations Rails should include in the serialized output.
When building a web application that uses JavaScript to retrieve JSON data from the server, this mechanism has historically been the primary
way that Rails developers prepared their responses. This works great for simple cases, as the logic for serializing an Active Record object
is neatly encapsulated in Active Record itself.
However, this solution quickly falls apart in the face of serialization requirements based on authorization. For instance, a web service
may choose to expose additional information about a resource only if the user is entitled to access it. In addition, a JavaScript front-end
may want information that is not neatly described in terms of serializing a single Active Record object, or in a different format than.
In addition, neither the controller nor the model seems like the correct place for logic that describes how to serialize an model object
*for the current user*.
Serializers solve these problems by encapsulating serialization in an object designed for this purpose. If the default +to_json+ semantics,
with at most a few configuration options serve your needs, by all means continue to use the built-in +to_json+. If you find yourself doing
hash-driven-development in your controllers, juggling authorization logic and other concerns, serializers are for you!
h3. The Most Basic Serializer
A basic serializer is a simple Ruby object named after the model class it is serializing.
<pre lang="ruby">
class PostSerializer
def initialize(post, scope)
@post, @scope = post, scope
end
def as_json
{ post: { title: @post.name, body: @post.body } }
end
end
</pre>
A serializer is initialized with two parameters: the model object it should serialize and an authorization scope. By default, the
authorization scope is the current user (+current_user+) but you can use a different object if you want. The serializer also
implements an +as_json+ method, which returns a Hash that will be sent to the JSON encoder.
Rails will transparently use your serializer when you use +render :json+ in your controller.
<pre lang="ruby">
class PostsController < ApplicationController
def show
@post = Post.find(params[:id])
render json: @post
end
end
</pre>
Because +respond_with+ uses +render :json+ under the hood for JSON requests, Rails will automatically use your serializer when
you use +respond_with+ as well.
h4. +serializable_hash+
In general, you will want to implement +serializable_hash+ and +as_json+ to allow serializers to embed associated content
directly. The easiest way to implement these two methods is to have +as_json+ call +serializable_hash+ and insert the root.
<pre lang="ruby">
class PostSerializer
def initialize(post, scope)
@post, @scope = post, scope
end
def serializable_hash
{ title: @post.name, body: @post.body }
end
def as_json
{ post: serializable_hash }
end
end
</pre>
h4. Authorization
Let's update our serializer to include the email address of the author of the post, but only if the current user has superuser
access.
<pre lang="ruby">
class PostSerializer
def initialize(post, scope)
@post, @scope = post, scope
end
def as_json
{ post: serializable_hash }
end
def serializable_hash
hash = post
hash.merge!(super_data) if super?
hash
end
private
def post
{ title: @post.name, body: @post.body }
end
def super_data
{ email: @post.email }
end
def super?
@scope.superuser?
end
end
</pre>
h4. Testing
One benefit of encapsulating our objects this way is that it becomes extremely straight-forward to test the serialization
logic in isolation.
<pre lang="ruby">
require "ostruct"
class PostSerializerTest < ActiveSupport::TestCase
# For now, we use a very simple authorization structure. These tests will need
# refactoring if we change that.
plebe = OpenStruct.new(super?: false)
god = OpenStruct.new(super?: true)
post = OpenStruct.new(title: "Welcome to my blog!", body: "Blah blah blah", email: "tenderlove@gmail.com")
test "a regular user sees just the title and body" do
json = PostSerializer.new(post, plebe).to_json
hash = JSON.parse(json)
assert_equal post.title, hash.delete("title")
assert_equal post.body, hash.delete("body")
assert_empty hash
end
test "a superuser sees the title, body and email" do
json = PostSerializer.new(post, god).to_json
hash = JSON.parse(json)
assert_equal post.title, hash.delete("title")
assert_equal post.body, hash.delete("body")
assert_equal post.email, hash.delete("email")
assert_empty hash
end
end
</pre>
It's important to note that serializer objects define a clear interface specifically for serializing an existing object.
In this case, the serializer expects to receive a post object with +name+, +body+ and +email+ attributes and an authorization
scope with a +super?+ method.
By defining a clear interface, it's must easier to ensure that your authorization logic is behaving correctly. In this case,
the serializer doesn't need to concern itself with how the authorization scope decides whether to set the +super?+ flag, just
whether it is set. In general, you should document these requirements in your serializer files and programatically via tests.
The documentation library +YARD+ provides excellent tools for describing this kind of requirement:
<pre lang="ruby">
class PostSerializer
# @param [~body, ~title, ~email] post the post to serialize
# @param [~super] scope the authorization scope for this serializer
def initialize(post, scope)
@post, @scope = post, scope
end
# ...
end
</pre>
h3. Attribute Sugar
To simplify this process for a number of common cases, Rails provides a default superclass named +ActiveModel::Serializer+
that you can use to implement your serializers.
For example, you will sometimes want to simply include a number of existing attributes from the source model into the outputted
JSON. In the above example, the +title+ and +body+ attributes were always included in the JSON. Let's see how to use
+ActiveModel::Serializer+ to simplify our post serializer.
<pre lang="ruby">
class PostSerializer < ActiveModel::Serializer
attributes :title, :body
def serializable_hash
hash = attributes
hash.merge!(super_data) if super?
hash
end
private
def super_data
{ email: @post.email }
end
def super?
@scope.superuser?
end
end
</pre>
First, we specified the list of included attributes at the top of the class. This will create an instance method called
+attributes+ that extracts those attributes from the post model.
NOTE: Internally, +ActiveModel::Serializer+ uses +read_attribute_for_serialization+, which defaults to +read_attribute+, which defaults to +send+. So if you're rolling your own models for use with the serializer, you can use simple Ruby accessors for your attributes if you like.
Next, we use the attributes method in our +serializable_hash+ method, which allowed us to eliminate the +post+ method we hand-rolled
earlier. We could also eliminate the +as_json+ method, as +ActiveModel::Serializer+ provides a default +as_json+ method for
us that calls our +serializable_hash+ method and inserts a root. But we can go a step further!
<pre lang="ruby">
class PostSerializer < ActiveModel::Serializer
attributes :title, :body
private
def attributes
hash = super
hash.merge!(email: post.email) if super?
hash
end
def super?
@scope.superuser?
end
end
</pre>
The superclass provides a default +initialize+ method as well as a default +serializable_hash+ method, which uses
+attributes+. We can call +super+ to get the hash based on the attributes we declared, and then add in any additional
attributes we want to use.
NOTE: +ActiveModel::Serializer+ will create an accessor matching the name of the current class for the resource you pass in. In this case, because we have defined a PostSerializer, we can access the resource with the +post+ accessor.
h3. Associations
In most JSON APIs, you will want to include associated objects with your serialized object. In this case, let's include
the comments with the current post.
<pre lang="ruby">
class PostSerializer < ActiveModel::Serializer
attributes :title, :body
has_many :comments
private
def attributes
hash = super
hash.merge!(email: post.email) if super?
hash
end
def super?
@scope.superuser?
end
end
</pre>
The default +serializable_hash+ method will include the comments as embedded objects inside the post.
<pre lang="json">
{
post: {
title: "Hello Blog!",
body: "This is my first post. Isn't it fabulous!",
comments: [
{
title: "Awesome",
body: "Your first post is great"
}
]
}
}
</pre>
Rails uses the same logic to generate embedded serializations as it does when you use +render :json+. In this case,
because you didn't define a +CommentSerializer+, Rails used the default +as_json+ on your comment object.
If you define a serializer, Rails will automatically instantiate it with the existing authorization scope.
<pre lang="ruby">
class CommentSerializer
def initialize(comment, scope)
@comment, @scope = comment, scope
end
def serializable_hash
{ title: @comment.title }
end
def as_json
{ comment: serializable_hash }
end
end
</pre>
If we define the above comment serializer, the outputted JSON will change to:
<pre lang="json">
{
post: {
title: "Hello Blog!",
body: "This is my first post. Isn't it fabulous!",
comments: [{ title: "Awesome" }]
}
}
</pre>
Let's imagine that our comment system allows an administrator to kill a comment, and we only want to allow
users to see the comments they're entitled to see. By default, +has_many :comments+ will simply use the
+comments+ accessor on the post object. We can override the +comments+ accessor to limit the comments used
to just the comments we want to allow for the current user.
<pre lang="ruby">
class PostSerializer < ActiveModel::Serializer
attributes :title. :body
has_many :comments
private
def attributes
hash = super
hash.merge!(email: post.email) if super?
hash
end
def comments
post.comments_for(scope)
end
def super?
@scope.superuser?
end
end
</pre>
+ActiveModel::Serializer+ will still embed the comments, but this time it will use just the comments
for the current user.
NOTE: The logic for deciding which comments a user should see still belongs in the model layer. In general, you should encapsulate concerns that require making direct Active Record queries in scopes or public methods on your models.
h4. Modifying Associations
You can also rename associations if required. Say for example you have an association that
makes sense to be named one thing in your code, but another when data is serialized.
You can use the <code:key</code> option to specify a different name for an association.
Here is an example:
<pre lang="ruby">
class UserSerializer < ActiveModel::Serializer
has_many :followed_posts, key: :posts
has_one :owned_account, key: :account
end
</pre>
Using the <code>:key</code> without a <code>:serializer</code> option will use implicit detection
to determine a serializer. In this example, you'd have to define two classes: <code>PostSerializer</code>
and <code>AccountSerializer</code>. You can also add the <code>:serializer</code> option
to set it explicitly:
<pre lang="ruby">
class UserSerializer < ActiveModel::Serializer
has_many :followed_posts, key: :posts, serializer: CustomPostSerializer
has_one :owne_account, key: :account, serializer: PrivateAccountSerializer
end
</pre>
h3. Customizing Associations
Not all front-ends expect embedded documents in the same form. In these cases, you can override the
default +serializable_hash+, and use conveniences provided by +ActiveModel::Serializer+ to avoid having to
build up the hash manually.
For example, let's say our front-end expects the posts and comments in the following format:
<pre lang="json">
{
post: {
id: 1
title: "Hello Blog!",
body: "This is my first post. Isn't it fabulous!",
comments: [1,2]
},
comments: [
{
id: 1
title: "Awesome",
body: "Your first post is great"
},
{
id: 2
title: "Not so awesome",
body: "Why is it so short!"
}
]
}
</pre>
We could achieve this with a custom +as_json+ method. We will also need to define a serializer for comments.
<pre lang="ruby">
class CommentSerializer < ActiveModel::Serializer
attributes :id, :title, :body
# define any logic for dealing with authorization-based attributes here
end
class PostSerializer < ActiveModel::Serializer
attributes :title, :body
has_many :comments
def as_json
{ post: serializable_hash }.merge!(associations)
end
def serializable_hash
post_hash = attributes
post_hash.merge!(association_ids)
post_hash
end
private
def attributes
hash = super
hash.merge!(email: post.email) if super?
hash
end
def comments
post.comments_for(scope)
end
def super?
@scope.superuser?
end
end
</pre>
Here, we used two convenience methods: +associations+ and +association_ids+. The first,
+associations+, creates a hash of all of the define associations, using their defined
serializers. The second, +association_ids+, generates a hash whose key is the association
name and whose value is an Array of the association's keys.
The +association_ids+ helper will use the overridden version of the association, so in
this case, +association_ids+ will only include the ids of the comments provided by the
+comments+ method.
h3. Special Association Serializers
So far, associations defined in serializers use either the +as_json+ method on the model
or the defined serializer for the association type. Sometimes, you may want to serialize
associated models differently when they are requested as part of another resource than
when they are requested on their own.
For instance, we might want to provide the full comment when it is requested directly,
but only its title when requested as part of the post. To achieve this, you can define
a serializer for associated objects nested inside the main serializer.
<pre lang="ruby">
class PostSerializer < ActiveModel::Serializer
class CommentSerializer < ActiveModel::Serializer
attributes :id, :title
end
# same as before
# ...
end
</pre>
In other words, if a +PostSerializer+ is trying to serialize comments, it will first
look for +PostSerializer::CommentSerializer+ before falling back to +CommentSerializer+
and finally +comment.as_json+.
h3. Overriding the Defaults
h4. Authorization Scope
By default, the authorization scope for serializers is +:current_user+. This means
that when you call +render json: @post+, the controller will automatically call
its +current_user+ method and pass that along to the serializer's initializer.
If you want to change that behavior, simply use the +serialization_scope+ class
method.
<pre lang="ruby">
class PostsController < ApplicationController
serialization_scope :current_app
end
</pre>
You can also implement an instance method called (no surprise) +serialization_scope+,
which allows you to define a dynamic authorization scope based on the current request.
WARNING: If you use different objects as authorization scopes, make sure that they all implement whatever interface you use in your serializers to control what the outputted JSON looks like.
h3. Using Serializers Outside of a Request
The serialization API encapsulates the concern of generating a JSON representation of
a particular model for a particular user. As a result, you should be able to easily use
serializers, whether you define them yourself or whether you use +ActiveModel::Serializer+
outside a request.
For instance, if you want to generate the JSON representation of a post for a user outside
of a request:
<pre lang="ruby">
user = get_user # some logic to get the user in question
PostSerializer.new(post, user).to_json # reliably generate JSON output
</pre>
If you want to generate JSON for an anonymous user, you should be able to use whatever
technique you use in your application to generate anonymous users outside of a request.
Typically, that means creating a new user and not saving it to the database:
<pre lang="ruby">
user = User.new # create a new anonymous user
PostSerializer.new(post, user).to_json
</pre>
In general, the better you encapsulate your authorization logic, the more easily you
will be able to use the serializer outside of the context of a request. For instance,
if you use an authorization library like Cancan, which uses a uniform +user.can?(action, model)+,
the authorization interface can very easily be replaced by a plain Ruby object for
testing or usage outside the context of a request.
h3. Collections
So far, we've talked about serializing individual model objects. By default, Rails
will serialize collections, including when using the +associations+ helper, by
looping over each element of the collection, calling +serializable_hash+ on the element,
and then grouping them by their type (using the plural version of their class name
as the root).
For example, an Array of post objects would serialize as:
<pre lang="json">
{
posts: [
{
title: "FIRST POST!",
body: "It's my first pooooost"
},
{ title: "Second post!",
body: "Zomg I made it to my second post"
}
]
}
</pre>
If you want to change the behavior of serialized Arrays, you need to create
a custom Array serializer.
<pre lang="ruby">
class ArraySerializer < ActiveModel::ArraySerializer
def serializable_array
serializers.map do |serializer|
serializer.serializable_hash
end
end
def as_json
hash = { root => serializable_array }
hash.merge!(associations)
hash
end
end
</pre>
When generating embedded associations using the +associations+ helper inside a
regular serializer, it will create a new <code>ArraySerializer</code> with the
associated content and call its +serializable_array+ method. In this case, those
embedded associations will not recursively include associations.
When generating an Array using +render json: posts+, the controller will invoke
the +as_json+ method, which will include its associations and its root.

100
Gemfile
View File

@ -1,100 +0,0 @@
source 'https://rubygems.org'
gemspec
version = ENV["RAILS_VERSION"] || "4.2"
if version == 'master'
gem 'rack', github: 'rack/rack'
gem 'arel', github: 'rails/arel'
gem 'rails', github: 'rails/rails'
git 'https://github.com/rails/rails.git' do
gem 'railties'
gem 'activesupport'
gem 'activemodel'
gem 'actionpack'
gem 'activerecord', group: :test
# Rails 5
gem 'actionview'
end
# Rails 5
gem 'rails-controller-testing', github: 'rails/rails-controller-testing'
else
gem_version = "~> #{version}.0"
gem 'rails', gem_version
gem 'railties', gem_version
gem 'activesupport', gem_version
gem 'activemodel', gem_version
gem 'actionpack', gem_version
gem 'activerecord', gem_version, group: :test
end
if RUBY_VERSION < '2'
gem 'mime-types', [ '>= 2.6.2', '< 3' ]
end
if ENV['CI']
if RUBY_VERSION < '2.4'
# Windows: An error occurred while installing nokogiri (1.8.0)
gem 'nokogiri', '< 1.7', platforms: @windows_platforms
# >= 4.0 requires ruby >= 2.5
gem 'sprockets', '< 4.0'
end
if RUBY_VERSION < '2.2'
# >= 12.3 and < 13 requires ruby >= 2.0, rake >= 13 requires ruby >= 2.2
gem 'rake', '< 12.3'
# > 5.12 requires ruby >= 2.2
gem 'minitest', '< 5.12'
# >= 1.0 requires ruby >= 2.0
gem 'thor', '< 1.0'
end
end
# https://github.com/bundler/bundler/blob/89a8778c19269561926cea172acdcda241d26d23/lib/bundler/dependency.rb#L30-L54
@windows_platforms = [:mswin, :mingw, :x64_mingw]
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
tzinfo_platforms = @windows_platforms
tzinfo_platforms += [:jruby] if version >= '4.1'
gem 'tzinfo-data', platforms: tzinfo_platforms
group :bench do
gem 'benchmark-ips', '>= 2.7.2'
end
group :test do
platforms(*(@windows_platforms + [:ruby])) do
if version == 'master' || version >= '6'
gem 'sqlite3', '~> 1.4'
else
gem 'sqlite3', '~> 1.3.13'
end
end
platforms :jruby do
if version == 'master' || version >= '6.0'
gem 'activerecord-jdbcsqlite3-adapter', github: 'jruby/activerecord-jdbc-adapter'
elsif version == '5.2'
gem 'activerecord-jdbcsqlite3-adapter', '~> 52.0'
elsif version == '5.1'
gem 'activerecord-jdbcsqlite3-adapter', '~> 51.0'
elsif version == '5.0'
gem 'activerecord-jdbcsqlite3-adapter', '~> 50.0'
else
gem 'activerecord-jdbcsqlite3-adapter', '~> 1.3.0'
end
end
end
group :development, :test do
unless ENV['CI']
gem 'rubocop', '~> 0.34.0', require: false
end
# 0.12 requires ruby 2.4
if RUBY_VERSION < '2.4'
gem 'simplecov', '< 0.12', require: false
else
gem 'simplecov', '~> 0.10', require: false
end
end

View File

@ -1,4 +1,6 @@
Copyright (c) 2011-2012 José Valim & Yehuda Katz
Copyright (c) 2014 Steve Klabnik
MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@ -18,4 +20,3 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

1003
README.md

File diff suppressed because it is too large Load Diff

View File

@ -1,24 +1,5 @@
#!/usr/bin/env rake
require "bundler/gem_tasks"
require "rake/testtask"
desc 'Run tests'
test_task = Rake::TestTask.new(:test) do |t|
t.libs << 'test'
t.pattern = 'test/**/*_test.rb'
t.verbose = true
end
task default: :test
desc 'Run tests in isolated processes'
namespace :test do
task :isolated do
Dir[test_task.pattern].each do |file|
cmd = ['ruby']
test_task.libs.each { |l| cmd << '-I' << l }
cmd << file
sh cmd.join(' ')
end
end
begin
require 'bundler/setup'
rescue LoadError
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
end

View File

@ -1,26 +1,20 @@
# -*- encoding: utf-8 -*-
# coding: utf-8
$:.unshift File.expand_path("../lib", __FILE__)
require "active_model/serializer/version"
Gem::Specification.new do |spec|
spec.name = 'active_model_serializers'
spec.version = "1.0.0-dev"
spec.platform = Gem::Platform::RUBY
spec.authors = ['Steve Klabnik']
spec.email = ['steve@steveklabnik.com']
spec.summary = 'Conventions-based JSON generation for Rails.'
spec.description = 'ActiveModel::Serializers allows you to generate your JSON in an object-oriented and convention-driven manner.'
spec.homepage = 'https://github.com/rails-api/active_model_serializers'
spec.license = 'MIT'
Gem::Specification.new do |gem|
gem.authors = ["José Valim", "Yehuda Katz", "Santiago Pastorino"]
gem.email = ["jose.valim@gmail.com", "wycats@gmail.com", "santiago@wyeworks.com"]
gem.description = %q{Making it easy to serialize models for client-side use}
gem.summary = %q{Bringing consistency and object orientation to model serialization. Works great for client-side MVC frameworks!}
gem.homepage = "https://github.com/rails-api/active_model_serializers"
gem.license = 'MIT'
spec.files = `git ls-files -z`.split("\x0")
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = ['lib']
spec.executables = []
gem.files = Dir['README.md', 'CHANGELOG.md', 'CONTRIBUTING.md', 'DESIGN.textile', 'MIT-LICENSE', 'lib/**/*', 'test/**/*']
gem.test_files = Dir['test/**/*']
gem.name = "active_model_serializers"
gem.require_paths = ["lib"]
gem.version = ActiveModel::Serializer::VERSION
gem.required_ruby_version = ">= 1.9.3"
gem.add_dependency "activemodel", ">= 3.2"
gem.add_dependency "concurrent-ruby", "~> 1.0"
gem.add_development_dependency "rails", ">= 3.2"
spec.required_ruby_version = '>= 2.1'
end

View File

@ -1,27 +1,11 @@
version: '{build}'
skip_tags: true
environment:
matrix:
- ruby_version: "200"
- ruby_version: "200-x64"
- ruby_version: "21"
- ruby_version: "21-x64"
cache:
- vendor/bundle
install:
- SET PATH=C:\Ruby%ruby_version%\bin;%PATH%
- ruby --version
- gem --version
- gem install bundler -v 1.17.3
- bundler --version
- bundle platform
- bundle install --path=vendor/bundle --retry=3 --jobs=3
test_script:
- bundle exec rake test
build: off
version: 1.0.{build}-{branch}
skip_tags: true
cache:
- vendor/bundle
test_script:
- true
build: off

171
bin/bench
View File

@ -1,171 +0,0 @@
#!/usr/bin/env ruby
# ActiveModelSerializers Benchmark driver
# Adapted from
# https://github.com/ruby-bench/ruby-bench-suite/blob/8ad567f7e43a044ae48c36833218423bb1e2bd9d/rails/benchmarks/driver.rb
require 'bundler'
Bundler.setup
require 'json'
require 'pathname'
require 'optparse'
require 'digest'
require 'pathname'
require 'shellwords'
require 'logger'
require 'English'
class BenchmarkDriver
ROOT = Pathname File.expand_path(File.join('..', '..'), __FILE__)
BASE = ENV.fetch('BASE') { ROOT.join('test', 'benchmark') }
ESCAPED_BASE = Shellwords.shellescape(BASE)
def self.benchmark(options)
new(options).run
end
def self.parse_argv_and_run(argv = ARGV, options = {})
options = {
repeat_count: 1,
pattern: [],
env: 'CACHE_ON=on'
}.merge!(options)
OptionParser.new do |opts|
opts.banner = 'Usage: bin/bench [options]'
opts.on('-r', '--repeat-count [NUM]', 'Run benchmarks [NUM] times taking the best result') do |value|
options[:repeat_count] = value.to_i
end
opts.on('-p', '--pattern <PATTERN1,PATTERN2,PATTERN3>', 'Benchmark name pattern') do |value|
options[:pattern] = value.split(',')
end
opts.on('-e', '--env <var1=val1,var2=val2,var3=vale>', 'ENV variables to pass in') do |value|
options[:env] = value.split(',')
end
end.parse!(argv)
benchmark(options)
end
attr_reader :commit_hash, :base
# Based on logfmt:
# https://www.brandur.org/logfmt
# For more complete implementation see:
# see https://github.com/arachnid-cb/logfmtr/blob/master/lib/logfmtr/base.rb
# For usage see:
# https://blog.codeship.com/logfmt-a-log-format-thats-easy-to-read-and-write/
# https://engineering.heroku.com/blogs/2014-09-05-hutils-explore-your-structured-data-logs/
# For Ruby parser see:
# https://github.com/cyberdelia/logfmt-ruby
def self.summary_logger(device = 'output.txt')
require 'time'
logger = Logger.new(device)
logger.level = Logger::INFO
logger.formatter = proc { |severity, datetime, progname, msg|
msg = "'#{msg}'"
"level=#{severity} time=#{datetime.utc.iso8601(6)} pid=#{Process.pid} progname=#{progname} msg=#{msg}#{$INPUT_RECORD_SEPARATOR}"
}
logger
end
def self.stdout_logger
logger = Logger.new(STDOUT)
logger.level = Logger::INFO
logger.formatter = proc { |_, _, _, msg| "#{msg}#{$INPUT_RECORD_SEPARATOR}" }
logger
end
def initialize(options)
@writer = ENV['SUMMARIZE'] ? self.class.summary_logger : self.class.stdout_logger
@repeat_count = options[:repeat_count]
@pattern = options[:pattern]
@commit_hash = options.fetch(:commit_hash) { `git rev-parse --short HEAD`.chomp }
@base = options.fetch(:base) { ESCAPED_BASE }
@env = Array(options[:env]).join(' ')
@rubyopt = options[:rubyopt] # TODO: rename
end
def run
files.each do |path|
next if !@pattern.empty? && /#{@pattern.join('|')}/ !~ File.basename(path)
run_single(Shellwords.shellescape(path))
end
end
private
def files
Dir[File.join(base, 'bm_*')]
end
def run_single(path)
script = "RAILS_ENV=production #{@env} ruby #{@rubyopt} #{path}"
environment = `ruby -v`.chomp.strip[/\d+\.\d+\.\d+\w+/]
runs_output = measure(script)
if runs_output.empty?
results = { error: :no_results }
return
end
results = {}
results['commit_hash'] = commit_hash
results['version'] = runs_output.first['version']
results['rails_version'] = runs_output.first['rails_version']
results['benchmark_run[environment]'] = environment
results['runs'] = []
runs_output.each do |output|
results['runs'] << {
'benchmark_type[category]' => output['label'],
'benchmark_run[result][iterations_per_second]' => output['iterations_per_second'].round(3),
'benchmark_run[result][total_allocated_objects_per_iteration]' => output['total_allocated_objects_per_iteration']
}
end
ensure
results && report(results)
end
def report(results)
@writer.info { 'Benchmark results:' }
@writer.info { JSON.pretty_generate(results) }
end
def summarize(result)
puts "#{result['label']} #{result['iterations_per_second']}/ips; #{result['total_allocated_objects_per_iteration']} objects"
end
# FIXME: ` provides the full output but it'll return failed output as well.
def measure(script)
results = Hash.new { |h, k| h[k] = [] }
@repeat_count.times do
output = sh(script)
output.each_line do |line|
next if line.nil?
begin
result = JSON.parse(line)
rescue JSON::ParserError
result = { error: line } # rubocop:disable Lint/UselessAssignment
else
summarize(result)
results[result['label']] << result
end
end
end
results.map do |_, bm_runs|
bm_runs.sort_by do |run|
run['iterations_per_second']
end.last
end
end
def sh(cmd)
`#{cmd}`
end
end
BenchmarkDriver.parse_argv_and_run if $PROGRAM_NAME == __FILE__

15
docs/rfcs/template.md Normal file
View File

@ -0,0 +1,15 @@
- Start Date: (YYYY-MM-DD)
- RFC PR: https://github.com/rails-api/active_model_serializers/pull/dddd
- ActiveModelSerializers Issue: https://github.com/rails-api/active_model_serializers/issues/dddd
# Summary
# Motivation
# Detailed design
# Drawbacks
# Alternatives
# Unresolved questions

View File

@ -1,107 +0,0 @@
require 'active_support/core_ext/class/attribute'
module ActionController
# Action Controller Serialization
#
# Overrides render :json to check if the given object implements +active_model_serializer+
# as a method. If so, use the returned serializer instead of calling +to_json+ on the object.
#
# This module also provides a serialization_scope method that allows you to configure the
# +serialization_scope+ of the serializer. Most apps will likely set the +serialization_scope+
# to the current user:
#
# class ApplicationController < ActionController::Base
# serialization_scope :current_user
# end
#
# If you need more complex scope rules, you can simply override the serialization_scope:
#
# class ApplicationController < ActionController::Base
# private
#
# def serialization_scope
# current_user
# end
# end
#
module Serialization
extend ActiveSupport::Concern
include ActionController::Renderers
class << self
attr_accessor :enabled
end
self.enabled = true
included do
class_attribute :_serialization_scope
self._serialization_scope = :current_user
end
module ClassMethods
def serialization_scope(scope)
self._serialization_scope = scope
end
end
[:_render_option_json, :_render_with_renderer_json].each do |renderer_method|
define_method renderer_method do |resource, options|
serializer = build_json_serializer(resource, options)
if serializer
super(serializer, options)
else
super(resource, options)
end
end
end
private
def namespace_for_serializer
@namespace_for_serializer ||= namespace_for_class(self.class) unless namespace_for_class(self.class) == Object
end
def namespace_for_class(klass)
if Module.method_defined?(:module_parent)
klass.module_parent
else
klass.parent
end
end
def default_serializer(resource)
options = {}.tap do |o|
o[:namespace] = namespace_for_serializer if namespace_for_serializer
end
ActiveModel::Serializer.serializer_for(resource, options)
end
def default_serializer_options
{}
end
def serialization_scope
_serialization_scope = self.class._serialization_scope
send(_serialization_scope) if _serialization_scope && respond_to?(_serialization_scope, true)
end
def build_json_serializer(resource, options = {})
options = default_serializer_options.merge(options)
@namespace_for_serializer = options.fetch(:namespace, nil)
if serializer = options.fetch(:serializer, default_serializer(resource))
options[:scope] = serialization_scope unless options.has_key?(:scope)
if resource.respond_to?(:to_ary)
options[:resource_name] = controller_name
options[:namespace] = namespace_for_serializer if namespace_for_serializer
end
serializer.new(resource, options)
end
end
end
end

View File

@ -1,79 +0,0 @@
module ActionController
module SerializationAssertions
extend ActiveSupport::Concern
included do
setup :setup_serialization_subscriptions
teardown :teardown_serialization_subscriptions
end
def setup_serialization_subscriptions
@serializers = Hash.new(0)
ActiveSupport::Notifications.subscribe("!serialize.active_model_serializers") do |name, start, finish, id, payload|
serializer = payload[:serializer]
@serializers[serializer] += 1
end
end
def teardown_serialization_subscriptions
ActiveSupport::Notifications.unsubscribe("!serialize.active_model_serializers")
end
def process(*args)
@serializers = Hash.new(0)
super
end
# Asserts that the request was rendered with the appropriate serializers.
#
# # assert that the "PostSerializer" serializer was rendered
# assert_serializer "PostSerializer"
#
# # assert that the instance of PostSerializer was rendered
# assert_serializer PostSerializer
#
# # assert that the "PostSerializer" serializer was rendered
# assert_serializer :post_serializer
#
# # assert that the rendered serializer starts with "Post"
# assert_serializer %r{\APost.+\Z}
#
# # assert that no serializer was rendered
# assert_serializer nil
#
#
def assert_serializer(options = {}, message = nil)
# Force body to be read in case the template is being streamed.
response.body
rendered = @serializers
msg = message || "expecting <#{options.inspect}> but rendering with <#{rendered.keys}>"
matches_serializer = case options
when lambda { |options| options.kind_of?(Class) && options < ActiveModel::Serializer }
rendered.any? do |serializer, count|
options.name == serializer
end
when Symbol
options = options.to_s.camelize
rendered.any? do |serializer, count|
serializer == options
end
when String
!options.empty? && rendered.any? do |serializer, count|
serializer == options
end
when Regexp
rendered.any? do |serializer, count|
serializer.match(options)
end
when NilClass
rendered.blank?
else
raise ArgumentError, "assert_serializer only accepts a String, Symbol, Regexp, ActiveModel::Serializer, or nil"
end
assert matches_serializer, msg
end
end
end

View File

@ -1,68 +0,0 @@
require 'active_model/default_serializer'
require 'active_model/serializable'
module ActiveModel
class ArraySerializer
include Serializable
class << self
attr_accessor :_root
alias root _root=
alias root= _root=
end
def initialize(object, options={})
@object = object
@scope = options[:scope]
@root = options.fetch(:root, self.class._root)
@polymorphic = options.fetch(:polymorphic, false)
@meta_key = options[:meta_key] || :meta
@meta = options[@meta_key]
@each_serializer = options[:each_serializer]
@resource_name = options[:resource_name]
@only = options[:only] ? Array(options[:only]) : nil
@except = options[:except] ? Array(options[:except]) : nil
@context = options[:context]
@namespace = options[:namespace]
@key_format = options[:key_format] || options[:each_serializer].try(:key_format)
end
attr_accessor :object, :scope, :root, :meta_key, :meta, :key_format, :context
def json_key
key = root.nil? ? @resource_name : root
key_format == :lower_camel && key.present? ? key.camelize(:lower) : key
end
def serializer_for(item)
serializer_class = @each_serializer || Serializer.serializer_for(item, namespace: @namespace) || DefaultSerializer
serializer_class.new(item, scope: scope, key_format: key_format, context: @context, only: @only, except: @except, polymorphic: @polymorphic, namespace: @namespace)
end
def serializable_object(options={})
@object.map do |item|
serializer_for(item).serializable_object_with_notification(options)
end
end
alias_method :serializable_array, :serializable_object
def embedded_in_root_associations
@object.each_with_object({}) do |item, hash|
serializer_for(item).embedded_in_root_associations.each_pair do |type, objects|
next if !objects || objects.flatten.empty?
if hash.has_key?(type)
case hash[type] when Hash
hash[type].deep_merge!(objects){ |key, old, new| (Array(old) + Array(new)).uniq }
else
hash[type].concat(objects).uniq!
end
else
hash[type] = objects
end
end
end
end
end
end

View File

@ -1,28 +0,0 @@
require 'active_model/serializable'
module ActiveModel
# DefaultSerializer
#
# Provides a constant interface for all items
class DefaultSerializer
include ActiveModel::Serializable
attr_reader :object
def initialize(object, options={})
@object = object
@wrap_in_array = options[:_wrap_in_array]
end
def as_json(options={})
instrument do
return [] if @object.nil? && @wrap_in_array
hash = @object.as_json
@wrap_in_array ? [hash] : hash
end
end
alias serializable_hash as_json
alias serializable_object as_json
end
end

View File

@ -1,59 +0,0 @@
require 'active_model/serializable/utils'
module ActiveModel
module Serializable
INSTRUMENTATION_KEY = '!serialize.active_model_serializers'.freeze
def self.included(base)
base.extend Utils
end
def as_json(options={})
instrument do
if root = options.fetch(:root, json_key)
hash = { root => serializable_object(options) }
hash.merge!(serializable_data)
hash
else
serializable_object(options)
end
end
end
def serializable_object_with_notification(options={})
instrument { serializable_object(options) }
end
def serializable_data
embedded_in_root_associations.tap do |hash|
if respond_to?(:meta) && meta
hash[meta_key] = meta
end
end
end
def namespace
if module_name = get_namespace
Serializer.serializers_cache.fetch_or_store(module_name) do
Utils._const_get(module_name)
end
end
end
def embedded_in_root_associations
{}
end
private
def get_namespace
modules = self.class.name.split('::')
modules[0..-2].join('::') if modules.size > 1
end
def instrument(&block)
payload = { serializer: self.class.name }
ActiveSupport::Notifications.instrument(INSTRUMENTATION_KEY, payload, &block)
end
end
end

View File

@ -1,16 +0,0 @@
module ActiveModel
module Serializable
module Utils
extend self
def _const_get(const)
begin
method = RUBY_VERSION >= '2.0' ? :const_get : :qualified_const_get
Object.send method, const
rescue NameError
const.safe_constantize
end
end
end
end
end

View File

@ -1,318 +0,0 @@
require 'active_model/array_serializer'
require 'active_model/serializable'
require 'active_model/serializer/association'
require 'active_model/serializer/config'
require 'thread'
require 'concurrent/map'
module ActiveModel
class Serializer
include Serializable
@mutex = Mutex.new
class << self
def inherited(base)
base._root = _root
base._attributes = (_attributes || []).dup
base._associations = (_associations || {}).dup
end
def setup
@mutex.synchronize do
yield CONFIG
end
end
EMBED_IN_ROOT_OPTIONS = [
:include,
:embed_in_root,
:embed_in_root_key,
:embed_namespace
].freeze
def embed(type, options={})
CONFIG.embed = type
if EMBED_IN_ROOT_OPTIONS.any? { |opt| options[opt].present? }
CONFIG.embed_in_root = true
end
if options[:embed_in_root_key].present?
CONFIG.embed_in_root_key = options[:embed_in_root_key]
end
ActiveSupport::Deprecation.warn <<-WARN
** Notice: embed is deprecated. **
The use of .embed method on a Serializer will be soon removed, as this should have a global scope and not a class scope.
Please use the global .setup method instead:
ActiveModel::Serializer.setup do |config|
config.embed = :#{type}
config.embed_in_root = #{CONFIG.embed_in_root || false}
end
WARN
end
def format_keys(format)
@key_format = format
end
attr_reader :key_format
def serializer_for(resource, options = {})
if resource.respond_to?(:serializer_class)
resource.serializer_class
elsif resource.respond_to?(:to_ary)
if Object.constants.include?(:ArraySerializer)
::ArraySerializer
else
ArraySerializer
end
else
klass_name = build_serializer_class(resource, options)
Serializer.serializers_cache.fetch_or_store(klass_name) do
_const_get(klass_name)
end
end
end
attr_accessor :_root, :_attributes, :_associations
alias root _root=
alias root= _root=
def root_name
if name
root_name = name.demodulize.underscore.sub(/_serializer$/, '')
CONFIG.plural_default_root ? root_name.pluralize : root_name
end
end
def attributes(*attrs)
attrs.each do |attr|
striped_attr = strip_attribute attr
@_attributes << striped_attr
define_method striped_attr do
object.read_attribute_for_serialization attr
end unless method_defined?(attr)
end
end
def has_one(*attrs)
associate(Association::HasOne, *attrs)
end
def has_many(*attrs)
associate(Association::HasMany, *attrs)
end
def serializers_cache
@serializers_cache ||= Concurrent::Map.new
end
private
def strip_attribute(attr)
symbolized = attr.is_a?(Symbol)
attr = attr.to_s.gsub(/\?\Z/, '')
attr = attr.to_sym if symbolized
attr
end
def build_serializer_class(resource, options)
"".tap do |klass_name|
klass_name << "#{options[:namespace]}::" if options[:namespace]
klass_name << options[:prefix].to_s.classify if options[:prefix]
klass_name << "#{resource.class.name}Serializer"
end
end
def associate(klass, *attrs)
options = attrs.extract_options!
attrs.each do |attr|
define_method attr do
object.send attr
end unless method_defined?(attr)
@_associations[attr] = klass.new(attr, options)
end
end
end
def initialize(object, options={})
@object = object
@scope = options[:scope]
@root = options.fetch(:root, self.class._root)
@polymorphic = options.fetch(:polymorphic, false)
@meta_key = options[:meta_key] || :meta
@meta = options[@meta_key]
@wrap_in_array = options[:_wrap_in_array]
@only = options[:only] ? Array(options[:only]) : nil
@except = options[:except] ? Array(options[:except]) : nil
@key_format = options[:key_format]
@context = options[:context]
@namespace = options[:namespace]
end
attr_accessor :object, :scope, :root, :meta_key, :meta, :key_format, :context, :polymorphic
def json_key
key = if root == true || root.nil?
self.class.root_name
else
root
end
key_format == :lower_camel && key.present? ? key.camelize(:lower) : key
end
def attributes
filter(self.class._attributes.dup).each_with_object({}) do |name, hash|
hash[name] = send(name)
end
end
def associations(options={})
associations = self.class._associations
included_associations = filter(associations.keys)
associations.each_with_object({}) do |(name, association), hash|
if included_associations.include? name
if association.embed_ids?
ids = serialize_ids association
if association.embed_namespace?
hash = hash[association.embed_namespace] ||= {}
hash[association.key] = ids
else
hash[association.key] = ids
end
elsif association.embed_objects?
if association.embed_namespace?
hash = hash[association.embed_namespace] ||= {}
end
hash[association.embedded_key] = serialize association, options
end
end
end
end
def filter(keys)
if @only
keys & @only
elsif @except
keys - @except
else
keys
end
end
def embedded_in_root_associations
associations = self.class._associations
included_associations = filter(associations.keys)
associations.each_with_object({}) do |(name, association), hash|
if included_associations.include? name
association_serializer = build_serializer(association)
# we must do this always because even if the current association is not
# embedded in root, it might have its own associations that are embedded in root
hash.merge!(association_serializer.embedded_in_root_associations) do |key, oldval, newval|
if oldval.respond_to?(:to_ary)
[oldval, newval].flatten.uniq
else
oldval.merge(newval) { |_, oldval, newval| [oldval, newval].flatten.uniq }
end
end
if association.embed_in_root?
if association.embed_in_root_key?
hash = hash[association.embed_in_root_key] ||= {}
end
serialized_data = association_serializer.serializable_object
key = association.root_key
if hash.has_key?(key)
hash[key].concat(serialized_data).uniq!
else
hash[key] = serialized_data
end
end
end
end
end
def build_serializer(association)
object = send(association.name)
association.build_serializer(object, association_options_for_serializer(association))
end
def association_options_for_serializer(association)
prefix = association.options[:prefix]
namespace = association.options[:namespace] || @namespace || self.namespace
{ scope: scope }.tap do |opts|
opts[:namespace] = namespace if namespace
opts[:prefix] = prefix if prefix
end
end
def serialize(association,options={})
build_serializer(association).serializable_object(options)
end
def serialize_ids(association)
associated_data = send(association.name)
if associated_data.respond_to?(:to_ary)
associated_data.map { |elem| serialize_id(elem, association) }
else
serialize_id(associated_data, association) if associated_data
end
end
def key_format
@key_format || self.class.key_format || CONFIG.key_format
end
def format_key(key)
if key_format == :lower_camel
key.to_s.camelize(:lower)
else
key
end
end
def convert_keys(hash)
Hash[hash.map do |k,v|
key = if k.is_a?(Symbol)
format_key(k).to_sym
else
format_key(k)
end
[key ,v]
end]
end
attr_writer :serialization_options
def serialization_options
@serialization_options || {}
end
def serializable_object(options={})
self.serialization_options = options
return @wrap_in_array ? [] : nil if @object.nil?
hash = attributes
hash.merge! associations(options)
hash = convert_keys(hash) if key_format.present?
hash = { :type => type_name(@object), type_name(@object) => hash } if @polymorphic
@wrap_in_array ? [hash] : hash
end
alias_method :serializable_hash, :serializable_object
def serialize_id(elem, association)
id = elem.read_attribute_for_serialization(association.embed_key)
association.polymorphic? ? { id: id, type: type_name(elem) } : id
end
def type_name(elem)
elem.class.to_s.demodulize.underscore.to_sym
end
end
end

View File

@ -1,58 +0,0 @@
require 'active_model/default_serializer'
require 'active_model/serializer/association/has_one'
require 'active_model/serializer/association/has_many'
module ActiveModel
class Serializer
class Association
def initialize(name, options={})
if options.has_key?(:include)
ActiveSupport::Deprecation.warn <<-WARN
** Notice: include was renamed to embed_in_root. **
WARN
end
@name = name.to_s
@options = options
self.embed = options.fetch(:embed) { CONFIG.embed }
@polymorphic = options.fetch(:polymorphic, false)
@embed_in_root = options.fetch(:embed_in_root) { options.fetch(:include) { CONFIG.embed_in_root } }
@key_format = options.fetch(:key_format) { CONFIG.key_format }
@embed_key = options[:embed_key] || :id
@key = options[:key]
@embedded_key = options[:root] || name
@embed_in_root_key = options.fetch(:embed_in_root_key) { CONFIG.embed_in_root_key }
@embed_namespace = options.fetch(:embed_namespace) { CONFIG.embed_namespace }
serializer = @options[:serializer]
@serializer_from_options = serializer.is_a?(String) ? serializer.constantize : serializer
end
attr_reader :name, :embed_ids, :embed_objects, :polymorphic
attr_accessor :embed_in_root, :embed_key, :key, :embedded_key, :root_key, :serializer_from_options, :options, :key_format, :embed_in_root_key, :embed_namespace
alias embed_ids? embed_ids
alias embed_objects? embed_objects
alias embed_in_root? embed_in_root
alias embed_in_root_key? embed_in_root_key
alias embed_namespace? embed_namespace
alias polymorphic? polymorphic
def embed=(embed)
@embed_ids = embed == :id || embed == :ids
@embed_objects = embed == :object || embed == :objects
end
def serializer_from_object(object, options = {})
Serializer.serializer_for(object, options)
end
def default_serializer
DefaultSerializer
end
def build_serializer(object, options = {})
serializer_class(object, options).new(object, options.merge(self.options))
end
end
end
end

View File

@ -1,39 +0,0 @@
module ActiveModel
class Serializer
class Association
class HasMany < Association
def initialize(name, *args)
super
@root_key = @embedded_key.to_s
@key ||= case CONFIG.default_key_type
when :name then name.to_s.pluralize
else "#{name.to_s.singularize}_ids"
end
end
def serializer_class(object, _)
if use_array_serializer?
ArraySerializer
else
serializer_from_options
end
end
def options
if use_array_serializer?
{ each_serializer: serializer_from_options }.merge! super
else
super
end
end
private
def use_array_serializer?
!serializer_from_options ||
serializer_from_options && !(serializer_from_options <= ArraySerializer)
end
end
end
end
end

View File

@ -1,25 +0,0 @@
module ActiveModel
class Serializer
class Association
class HasOne < Association
def initialize(name, *args)
super
@root_key = @embedded_key.to_s.pluralize
@key ||= case CONFIG.default_key_type
when :name then name.to_s.singularize
else "#{name}_id"
end
end
def serializer_class(object, options = {})
(serializer_from_options unless object.nil?) || serializer_from_object(object, options) || default_serializer
end
def build_serializer(object, options = {})
options[:_wrap_in_array] = embed_in_root?
super
end
end
end
end
end

View File

@ -1,31 +0,0 @@
module ActiveModel
class Serializer
class Config
def initialize(data = {})
@data = data
end
def each(&block)
@data.each(&block)
end
def clear
@data.clear
end
def method_missing(name, *args)
name = name.to_s
return @data[name] if @data.include?(name)
match = name.match(/\A(.*?)([?=]?)\Z/)
case match[2]
when "="
@data[match[1]] = args.first
when "?"
!!@data[match[1]]
end
end
end
CONFIG = Config.new('embed' => :objects) # :nodoc:
end
end

View File

@ -1,13 +0,0 @@
require 'rails/generators'
require 'rails/generators/rails/resource/resource_generator'
module Rails
module Generators
class ResourceGenerator
def add_serializer
invoke 'serializer'
end
end
end
end

View File

@ -1,9 +0,0 @@
Description:
Generates a serializer for the given resource with tests.
Example:
`rails generate serializer Account name created_at`
For TestUnit it creates:
Serializer: app/serializers/account_serializer.rb
TestUnit: test/unit/account_serializer_test.rb

View File

@ -1,14 +0,0 @@
require 'rails/generators'
require 'rails/generators/rails/scaffold_controller/scaffold_controller_generator'
module Rails
module Generators
class ScaffoldControllerGenerator
if Rails::VERSION::MAJOR >= 4
source_root File.expand_path('../templates', __FILE__)
hook_for :serializer, default: true, type: :boolean
end
end
end
end

View File

@ -1,37 +0,0 @@
module Rails
module Generators
class SerializerGenerator < NamedBase
source_root File.expand_path('../templates', __FILE__)
check_class_collision suffix: 'Serializer'
argument :attributes, type: :array, default: [], banner: 'field:type field:type'
class_option :parent, type: :string, desc: 'The parent class for the generated serializer'
def create_serializer_file
template 'serializer.rb', File.join('app/serializers', class_path, "#{file_name}_serializer.rb")
end
private
def attributes_names
[:id] + attributes.select { |attr| !attr.reference? }.map { |a| a.name.to_sym }
end
def association_names
attributes.select { |attr| attr.reference? }.map { |a| a.name.to_sym }
end
def parent_class_name
if options[:parent]
options[:parent]
elsif (ns = Rails::Generators.namespace) && ns.const_defined?(:ApplicationSerializer) ||
(Object.const_get(:ApplicationSerializer) rescue nil)
'ApplicationSerializer'
else
'ActiveModel::Serializer'
end
end
end
end
end

View File

@ -1,93 +0,0 @@
<% if namespaced? -%>
require_dependency "<%= namespaced_file_path %>/application_controller"
<% end -%>
<% module_namespacing do -%>
class <%= controller_class_name %>Controller < ApplicationController
before_action :set_<%= singular_table_name %>, only: [:show, :edit, :update, :destroy]
# GET <%= route_url %>
# GET <%= route_url %>.json
def index
@<%= plural_table_name %> = <%= orm_class.all(class_name) %>
respond_to do |format|
format.html # index.html.erb
format.json { render json: <%= "@#{plural_table_name}" %> }
end
end
# GET <%= route_url %>/1
# GET <%= route_url %>/1.json
def show
respond_to do |format|
format.html # show.html.erb
format.json { render json: <%= "@#{singular_table_name}" %> }
end
end
# GET <%= route_url %>/new
def new
@<%= singular_table_name %> = <%= orm_class.build(class_name) %>
end
# GET <%= route_url %>/1/edit
def edit
end
# POST <%= route_url %>
# POST <%= route_url %>.json
def create
@<%= singular_table_name %> = <%= orm_class.build(class_name, "#{singular_table_name}_params") %>
respond_to do |format|
if @<%= orm_instance.save %>
format.html { redirect_to @<%= singular_table_name %>, notice: <%= "'#{human_name} was successfully created.'" %> }
format.json { render json: <%= "@#{singular_table_name}" %>, status: :created }
else
format.html { render action: 'new' }
format.json { render json: <%= "@#{orm_instance.errors}" %>, status: :unprocessable_entity }
end
end
end
# PATCH/PUT <%= route_url %>/1
# PATCH/PUT <%= route_url %>/1.json
def update
respond_to do |format|
if @<%= orm_instance.update("#{singular_table_name}_params") %>
format.html { redirect_to @<%= singular_table_name %>, notice: <%= "'#{human_name} was successfully updated.'" %> }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: <%= "@#{orm_instance.errors}" %>, status: :unprocessable_entity }
end
end
end
# DELETE <%= route_url %>/1
# DELETE <%= route_url %>/1.json
def destroy
@<%= orm_instance.destroy %>
respond_to do |format|
format.html { redirect_to <%= index_helper %>_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_<%= singular_table_name %>
@<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %>
end
# Never trust parameters from the scary internet, only allow the white list through.
def <%= "#{singular_table_name}_params" %>
<%- if attributes_names.empty? -%>
params[<%= ":#{singular_table_name}" %>]
<%- else -%>
params.require(<%= ":#{singular_table_name}" %>).permit(<%= attributes_names.map { |name| ":#{name}" }.join(', ') %>)
<%- end -%>
end
end
<% end -%>

View File

@ -1,8 +0,0 @@
<% module_namespacing do -%>
class <%= class_name %>Serializer < <%= parent_class_name %>
attributes <%= attributes_names.map(&:inspect).join(", ") %>
<% association_names.each do |attribute| -%>
has_one :<%= attribute %>
<% end -%>
end
<% end -%>

View File

@ -1,22 +0,0 @@
module ActiveModel
class Railtie < Rails::Railtie
initializer 'generators' do |app|
app.load_generators
require 'active_model/serializer/generators/serializer/serializer_generator'
require 'active_model/serializer/generators/serializer/scaffold_controller_generator'
require 'active_model/serializer/generators/resource_override'
end
initializer 'include_routes.active_model_serializer' do |app|
ActiveSupport.on_load(:active_model_serializers) do
include app.routes.url_helpers
end
end
config.to_prepare do
ActiveModel::Serializer.serializers_cache.clear
end
end
end
ActiveSupport.run_load_hooks(:active_model_serializers, ActiveModel::Serializer)

View File

@ -1,5 +0,0 @@
module ActiveModel
class Serializer
VERSION = '0.9.8'.freeze
end
end

View File

@ -1,5 +0,0 @@
module ActiveModel
module SerializerSupport
alias read_attribute_for_serialization send
end
end

View File

@ -1,20 +0,0 @@
require 'active_model'
require 'active_model/serializer'
require 'active_model/serializer_support'
require 'active_model/serializer/version'
require 'active_model/serializer/railtie' if defined?(Rails)
begin
require 'action_controller'
require 'action_controller/serialization'
require 'action_controller/serialization_test_case'
ActiveSupport.on_load(:action_controller) do
if ::ActionController::Serialization.enabled
ActionController::Base.send(:include, ::ActionController::Serialization)
ActionController::TestCase.send(:include, ::ActionController::SerializationAssertions)
end
end
rescue LoadError
# rails not installed, continuing
end

View File

@ -1,60 +0,0 @@
# https://github.com/rails-api/active_model_serializers/pull/872
# approx ref 792fb8a9053f8db3c562dae4f40907a582dd1720 to test against
require 'bundler/setup'
require 'rails'
require 'active_model'
require 'active_support'
require 'active_support/json'
require 'action_controller'
require 'action_controller/test_case'
require 'action_controller/railtie'
abort "Rails application already defined: #{Rails.application.class}" if Rails.application
class NullLogger < Logger
def initialize(*_args)
end
def add(*_args, &_block)
end
end
class BenchmarkLogger < ActiveSupport::Logger
def initialize
@file = StringIO.new
super(@file)
end
def messages
@file.rewind
@file.read
end
end
# ref: https://gist.github.com/bf4/8744473
class BenchmarkApp < Rails::Application
# Set up production configuration
config.eager_load = true
config.cache_classes = true
# CONFIG: CACHE_ON={on,off}
config.action_controller.perform_caching = ENV['CACHE_ON'] != 'off'
config.action_controller.cache_store = ActiveSupport::Cache.lookup_store(:memory_store)
config.active_support.test_order = :random
config.secret_token = 'S' * 30
config.secret_key_base = 'abc123'
config.consider_all_requests_local = false
# otherwise deadlock occurred
config.middleware.delete 'Rack::Lock'
# to disable log files
config.logger = NullLogger.new
config.active_support.deprecation = :log
config.log_level = :info
end
require 'active_model_serializers'
# Initialize app before any serializers are defined, for running across revisions.
# ref: https://github.com/rails-api/active_model_serializers/pull/1478
Rails.application.initialize!

View File

@ -1,67 +0,0 @@
require 'benchmark/ips'
require 'json'
# Add benchmarking runner from ruby-bench-suite
# https://github.com/ruby-bench/ruby-bench-suite/blob/master/rails/benchmarks/support/benchmark_rails.rb
module Benchmark
module ActiveModelSerializers
module TestMethods
def request(method, path)
response = Rack::MockRequest.new(BenchmarkApp).send(method, path)
if response.status.in?([404, 500])
fail "omg, #{method}, #{path}, '#{response.status}', '#{response.body}'"
end
response
end
end
# extend Benchmark with an `ams` method
def ams(label = nil, time:, disable_gc: true, warmup: 3, &block)
fail ArgumentError.new, 'block should be passed' unless block_given?
if disable_gc
GC.disable
else
GC.enable
end
report = Benchmark.ips(time, warmup, true) do |x|
x.report(label) { yield }
end
entry = report.entries.first
output = {
label: label,
version: ::ActiveModel::Serializer::VERSION.to_s,
rails_version: ::Rails.version.to_s,
iterations_per_second: entry.ips,
iterations_per_second_standard_deviation: entry.error_percentage,
total_allocated_objects_per_iteration: count_total_allocated_objects(&block)
}.to_json
puts output
output
end
def count_total_allocated_objects
if block_given?
key =
if RUBY_VERSION < '2.2'
:total_allocated_object
else
:total_allocated_objects
end
before = GC.stat[key]
yield
after = GC.stat[key]
after - before
else
-1
end
end
end
extend Benchmark::ActiveModelSerializers
end

View File

@ -1,41 +0,0 @@
require_relative './benchmarking_support'
require_relative './app'
require_relative './setup'
time = 10
disable_gc = true
authors_query = Author.preload(:posts).preload(:profile)
author = authors_query.first
authors = authors_query.to_a
Benchmark.ams('Single: DefaultSerializer', time: time, disable_gc: disable_gc) do
ActiveModel::DefaultSerializer.new(author).to_json
end
Benchmark.ams('ArraySerializer', time: time, disable_gc: disable_gc) do
ActiveModel::ArraySerializer.new(authors).to_json
end
Benchmark.ams('ArraySerializer: each_serializer: DefaultSerializer', time: time, disable_gc: disable_gc) do
ActiveModel::ArraySerializer.new(authors, each_serializer:ActiveModel::DefaultSerializer).to_json
end
Benchmark.ams('FlatAuthorSerializer', time: time, disable_gc: disable_gc) do
FlatAuthorSerializer.new(author).to_json
end
Benchmark.ams('ArraySerializer: each_serializer: FlatAuthorSerializer', time: time, disable_gc: disable_gc) do
ActiveModel::ArraySerializer.new(authors, each_serializer: FlatAuthorSerializer).to_json
end
Benchmark.ams('AuthorWithDefaultRelationshipsSerializer', time: time, disable_gc: disable_gc) do
AuthorWithDefaultRelationshipsSerializer.new(author).to_json
end
Benchmark.ams('ArraySerializer: each_serializer: AuthorWithDefaultRelationshipsSerializer', time: time, disable_gc: disable_gc) do
ActiveModel::ArraySerializer.new(authors, each_serializer: AuthorWithDefaultRelationshipsSerializer).to_json
end

View File

@ -1,75 +0,0 @@
###########################################
# Setup active record models
##########################################
require 'active_record'
require 'sqlite3'
# Change the following to reflect your database settings
ActiveRecord::Base.establish_connection(
adapter: 'sqlite3',
database: ':memory:'
)
# Don't show migration output when constructing fake db
ActiveRecord::Migration.verbose = false
ActiveRecord::Schema.define do
create_table :authors, force: true do |t|
t.string :name
end
create_table :posts, force: true do |t|
t.text :body
t.string :title
t.references :author
end
create_table :profiles, force: true do |t|
t.text :project_url
t.text :bio
t.date :birthday
t.references :author
end
end
class Author < ActiveRecord::Base
has_one :profile
has_many :posts
end
class Post < ActiveRecord::Base
belongs_to :author
end
class Profile < ActiveRecord::Base
belongs_to :author
end
# Build out the data to serialize
author = Author.create(name: 'Preston Sego')
Profile.create(project_url: 'https://github.com/NullVoxPopuli', author: author)
50.times do
Post.create(
body: 'something about how password restrictions are evil, and less secure, and with the math to prove it.',
title: 'Your bank is does not know how to do security',
author: author
)
end
ActiveModel::Serializer.root = false
ActiveModel::ArraySerializer.root = false
class FlatAuthorSerializer < ActiveModel::Serializer
attributes :id, :name
end
class AuthorWithDefaultRelationshipsSerializer < ActiveModel::Serializer
attributes :id, :name
has_one :profile
has_many :posts
end
# For debugging SQL output
#ActiveRecord::Base.logger = Logger.new(STDERR)

View File

@ -1,96 +0,0 @@
require 'active_record'
ActiveRecord::Base.establish_connection(
:adapter => 'sqlite3',
:database => ':memory:'
)
ActiveRecord::Schema.define do
create_table :ar_posts, force: true do |t|
t.string :title
t.text :body
t.belongs_to :ar_section, index: true
t.timestamps
end
create_table :ar_comments, force: true do |t|
t.text :body
t.belongs_to :ar_post, index: true
t.timestamps
end
create_table :ar_tags, force: true do |t|
t.string :name
end
create_table :ar_sections, force: true do |t|
t.string :name
end
create_table :ar_posts_tags, force: true do |t|
t.references :ar_post, :ar_tag, index: true
end
create_table :ar_comments_tags, force: true do |t|
t.references :ar_comment, :ar_tag, index: true
end
end
class ARPost < ActiveRecord::Base
has_many :ar_comments, class_name: 'ARComment'
has_and_belongs_to_many :ar_tags, class_name: 'ARTag', join_table: :ar_posts_tags
belongs_to :ar_section, class_name: 'ARSection'
end
class ARComment < ActiveRecord::Base
belongs_to :ar_post, class_name: 'ARPost'
has_and_belongs_to_many :ar_tags, class_name: 'ARTag', join_table: :ar_comments_tags
end
class ARTag < ActiveRecord::Base
end
class ARSection < ActiveRecord::Base
end
class ARPostSerializer < ActiveModel::Serializer
attributes :title, :body
has_many :ar_comments, :ar_tags
has_one :ar_section
end
class ARCommentSerializer < ActiveModel::Serializer
attributes :body
has_many :ar_tags
end
class ARTagSerializer < ActiveModel::Serializer
attributes :name
end
class ARSectionSerializer < ActiveModel::Serializer
attributes 'name'
end
class AREmbeddedSerializer < ActiveModel::Serializer
has_many :ar_tags, :ar_comments
end
ARPost.create(title: 'New post',
body: 'A body!!!',
ar_section: ARSection.create(name: 'ruby')).tap do |post|
short_tag = post.ar_tags.create(name: 'short')
whiny_tag = post.ar_tags.create(name: 'whiny')
happy_tag = ARTag.create(name: 'happy')
post.ar_comments.create(body: 'what a dumb post').tap do |comment|
comment.ar_tags.concat happy_tag, whiny_tag
end
post.ar_comments.create(body: 'i liked it').tap do |comment|
comment.ar_tags.concat happy_tag, short_tag
end
end

223
test/fixtures/poro.rb vendored
View File

@ -1,223 +0,0 @@
class Model
def initialize(hash = {})
@attributes = hash
end
def read_attribute_for_serialization(name)
if name == :id || name == 'id'
object_id
elsif respond_to?(name)
send name
else
@attributes[name]
end
end
end
###
## Models
###
class User < Model
def profile
@profile ||= Profile.new(name: 'N1', description: 'D1')
end
end
class UserInfo < Model
def user
@user ||= User.new(name: 'N1', email: 'E1')
end
end
class Profile < Model
end
class Category < Model
def posts
@posts ||= [Post.new(title: 'T1', body: 'B1'),
Post.new(title: 'T2', body: 'B2')]
end
end
class Post < Model
def comments
@comments ||= [Comment.new(content: 'C1'),
Comment.new(content: 'C2')]
end
end
class SpecialPost < Post
def special_comment
@special_comment ||= Comment.new(content: 'special')
end
end
class Type < Model
end
class SelfReferencingUser < Model
def type
@type ||= Type.new(name: 'N1')
end
def parent
@parent ||= SelfReferencingUserParent.new(name: 'N1')
end
end
class SelfReferencingUserParent < Model
def type
@type ||= Type.new(name: 'N2')
end
def parent
end
end
class Comment < Model
end
class WebLog < Model
end
class Interview < Model
def attachment
@attachment ||= Image.new(url: 'U1')
end
end
class Mail < Model
def attachments
@attachments ||= [Image.new(url: 'U1'),
Video.new(html: 'H1')]
end
end
class Image < Model
end
class Video < Model
end
###
## Serializers
###
class UserSerializer < ActiveModel::Serializer
attributes :name, :email
has_one :profile
end
class TypeSerializer < ActiveModel::Serializer
attributes :name
end
class SelfReferencingUserParentSerializer < ActiveModel::Serializer
attributes :name
has_one :type, serializer: TypeSerializer, embed: :ids, include: true
end
class SelfReferencingUserSerializer < ActiveModel::Serializer
attributes :name
has_one :type, serializer: TypeSerializer, embed: :ids, include: true
has_one :parent, serializer: SelfReferencingUserSerializer, embed: :ids, include: true
end
class UserInfoSerializer < ActiveModel::Serializer
has_one :user, serializer: UserSerializer
end
class ProfileSerializer < ActiveModel::Serializer
def description
description = object.read_attribute_for_serialization(:description)
scope ? "#{description} - #{scope}" : description
end
attributes :name, :description
end
class CategorySerializer < ActiveModel::Serializer
attributes :name
has_many :posts
end
class PostSerializer < ActiveModel::Serializer
attributes :title, :body
def title
keyword = serialization_options[:highlight_keyword]
title = object.read_attribute_for_serialization(:title)
title = title.gsub(keyword,"'#{keyword}'") if keyword
title
end
has_many :comments
end
class SpecialPostSerializer < ActiveModel::Serializer
attributes :title, :body
has_many :comments, root: :comments, embed_in_root: true, embed: :ids
has_one :special_comment, root: :comments, embed_in_root: true, embed: :ids
end
class CommentSerializer < ActiveModel::Serializer
attributes :content
end
class WebLogSerializer < ActiveModel::Serializer
attributes :name, :display_name
end
class WebLogLowerCamelSerializer < WebLogSerializer
format_keys :lower_camel
end
class InterviewSerializer < ActiveModel::Serializer
attributes :text
has_one :attachment, polymorphic: true
end
class MailSerializer < ActiveModel::Serializer
attributes :body
has_many :attachments, polymorphic: true
end
class ImageSerializer < ActiveModel::Serializer
attributes :url
end
class VideoSerializer < ActiveModel::Serializer
attributes :html
end
class ShortProfileSerializer < ::ProfileSerializer; end
module TestNamespace
class ProfileSerializer < ::ProfileSerializer; end
class UserSerializer < ::UserSerializer; end
end
ActiveModel::Serializer.setup do |config|
config.default_key_type = :name
end
class NameKeyUserSerializer < ActiveModel::Serializer
attributes :name, :email
has_one :profile
end
class NameKeyPostSerializer < ActiveModel::Serializer
attributes :title, :body
has_many :comments
end
ActiveModel::Serializer.setup do |config|
config.default_key_type = nil
end

View File

@ -1 +0,0 @@
<p>Hello.</p>

View File

@ -1,105 +0,0 @@
require 'test_helper'
module ActionController
module Serialization
class NamespacedSerializationTest < ActionController::TestCase
class TestNamespace::MyController < ActionController::Base
def render_profile_with_namespace
render json: Profile.new({ name: 'Name 1', description: 'Description 1'})
end
def render_profiles_with_namespace
render json: [Profile.new({ name: 'Name 1', description: 'Description 1'})]
end
def render_comment
render json: Comment.new(content: 'Comment 1')
end
def render_comments
render json: [Comment.new(content: 'Comment 1')]
end
def render_hash
render json: {message: 'not found'}, status: 404
end
end
tests TestNamespace::MyController
def test_render_profile_with_namespace
get :render_profile_with_namespace
assert_serializer TestNamespace::ProfileSerializer
end
def test_render_profiles_with_namespace
get :render_profiles_with_namespace
assert_serializer TestNamespace::ProfileSerializer
end
def test_fallback_to_a_version_without_namespace
get :render_comment
assert_serializer CommentSerializer
end
def test_array_fallback_to_a_version_without_namespace
get :render_comments
assert_serializer CommentSerializer
end
def test_render_hash_regression
get :render_hash
assert_equal JSON.parse(response.body), {'message' => 'not found'}
end
end
class OptionNamespacedSerializationTest < ActionController::TestCase
class MyController < ActionController::Base
def default_serializer_options
{
namespace: TestNamespace
}
end
def render_profile_with_namespace_option
render json: Profile.new({ name: 'Name 1', description: 'Description 1'})
end
def render_profiles_with_namespace_option
render json: [Profile.new({ name: 'Name 1', description: 'Description 1'})]
end
def render_comment
render json: Comment.new(content: 'Comment 1')
end
def render_comments
render json: [Comment.new(content: 'Comment 1')]
end
end
tests MyController
def test_render_profile_with_namespace_option
get :render_profile_with_namespace_option
assert_serializer TestNamespace::ProfileSerializer
end
def test_render_profiles_with_namespace_option
get :render_profiles_with_namespace_option
assert_serializer TestNamespace::ProfileSerializer
end
def test_fallback_to_a_version_without_namespace
get :render_comment
assert_serializer CommentSerializer
end
def test_array_fallback_to_a_version_without_namespace
get :render_comments
assert_serializer CommentSerializer
end
end
end
end

View File

@ -1,287 +0,0 @@
require 'test_helper'
module ActionController
module Serialization
class ImplicitSerializerTest < ActionController::TestCase
class MyController < ActionController::Base
def render_using_implicit_serializer
render json: Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
end
end
tests MyController
def test_render_using_implicit_serializer
get :render_using_implicit_serializer
assert_equal 'application/json', @response.content_type
assert_equal '{"profile":{"name":"Name 1","description":"Description 1"}}', @response.body
end
end
class ImplicitSerializerScopeTest < ActionController::TestCase
class MyController < ActionController::Base
def render_using_implicit_serializer_and_scope
render json: Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
end
private
def current_user
'current_user'
end
end
tests MyController
def test_render_using_implicit_serializer_and_scope
get :render_using_implicit_serializer_and_scope
assert_equal 'application/json', @response.content_type
assert_equal '{"profile":{"name":"Name 1","description":"Description 1 - current_user"}}', @response.body
end
end
class DefaultOptionsForSerializerScopeTest < ActionController::TestCase
class MyController < ActionController::Base
def default_serializer_options
{ scope: current_admin }
end
def render_using_scope_set_in_default_serializer_options
render json: Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
end
private
def current_user
'current_user'
end
def current_admin
'current_admin'
end
end
tests MyController
def test_render_using_scope_set_in_default_serializer_options
get :render_using_scope_set_in_default_serializer_options
assert_equal 'application/json', @response.content_type
assert_equal '{"profile":{"name":"Name 1","description":"Description 1 - current_admin"}}', @response.body
end
end
class ExplicitSerializerScopeTest < ActionController::TestCase
class MyController < ActionController::Base
def render_using_implicit_serializer_and_explicit_scope
render json: Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }), scope: current_admin
end
private
def current_user
'current_user'
end
def current_admin
'current_admin'
end
end
tests MyController
def test_render_using_implicit_serializer_and_explicit_scope
get :render_using_implicit_serializer_and_explicit_scope
assert_equal 'application/json', @response.content_type
assert_equal '{"profile":{"name":"Name 1","description":"Description 1 - current_admin"}}', @response.body
end
end
class OverridingSerializationScopeTest < ActionController::TestCase
class MyController < ActionController::Base
def render_overriding_serialization_scope
render json: Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
end
private
def current_user
'current_user'
end
def serialization_scope
'current_admin'
end
end
tests MyController
def test_render_overriding_serialization_scope
get :render_overriding_serialization_scope
assert_equal 'application/json', @response.content_type
assert_equal '{"profile":{"name":"Name 1","description":"Description 1 - current_admin"}}', @response.body
end
end
class CallingSerializationScopeTest < ActionController::TestCase
class MyController < ActionController::Base
def render_calling_serialization_scope
render json: Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
end
private
def current_user
'current_user'
end
serialization_scope :current_user
end
tests MyController
def test_render_calling_serialization_scope
get :render_calling_serialization_scope
assert_equal 'application/json', @response.content_type
assert_equal '{"profile":{"name":"Name 1","description":"Description 1 - current_user"}}', @response.body
end
end
class JSONDumpSerializerTest < ActionController::TestCase
class MyController < ActionController::Base
def render_using_json_dump
render json: JSON.dump(hello: 'world')
end
end
tests MyController
def test_render_using_json_dump
get :render_using_json_dump
assert_equal 'application/json', @response.content_type
assert_equal '{"hello":"world"}', @response.body
end
end
class RailsSerializerTest < ActionController::TestCase
class MyController < ActionController::Base
def render_using_rails_behavior
render json: [Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })], serializer: false
end
end
tests MyController
def test_render_using_rails_behavior
get :render_using_rails_behavior
assert_equal 'application/json', @response.content_type
assert_equal '[{"attributes":{"name":"Name 1","description":"Description 1","comments":"Comments 1"}}]', @response.body
end
end
class ArraySerializerTest < ActionController::TestCase
class MyController < ActionController::Base
def render_array
render json: [Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })]
end
end
tests MyController
def test_render_array
get :render_array
assert_equal 'application/json', @response.content_type
assert_equal '{"my":[{"name":"Name 1","description":"Description 1"}]}', @response.body
end
end
class LowerCamelArraySerializerTest < ActionController::TestCase
class WebLogController < ActionController::Base
def render_array
render json: [WebLog.new({name: 'Name 1', display_name: 'Display Name 1'}), WebLog.new({name: 'Name 2', display_name: 'Display Name 2'})], each_serializer: WebLogLowerCamelSerializer
end
end
tests WebLogController
def test_render_array
get :render_array
assert_equal 'application/json', @response.content_type
assert_equal '{"webLog":[{"name":"Name 1","displayName":"Display Name 1"},{"name":"Name 2","displayName":"Display Name 2"}]}', @response.body
end
end
class LowerCamelWoRootSerializerTest < ActionController::TestCase
class WebLogController < ActionController::Base
def render_without_root
render json: WebLog.new({name: 'Name 1', display_name: 'Display Name 1'}),
root: false,
serializer: WebLogLowerCamelSerializer
end
end
tests WebLogController
def test_render_without_root
get :render_without_root
assert_equal 'application/json', @response.content_type
assert_equal '{"name":"Name 1","displayName":"Display Name 1"}', @response.body
end
end
class LowerCamelArrayWoRootSerializerTest < ActionController::TestCase
class WebLogController < ActionController::Base
def render_array_without_root
render json: [WebLog.new({name: 'Name 1', display_name: 'Display Name 1'}),
WebLog.new({name: 'Name 2', display_name: 'Display Name 2'})],
root: false,
each_serializer: WebLogLowerCamelSerializer
end
end
tests WebLogController
def test_render_array_without_root
get :render_array_without_root
assert_equal 'application/json', @response.content_type
assert_equal '[{"name":"Name 1","displayName":"Display Name 1"},{"name":"Name 2","displayName":"Display Name 2"}]', @response.body
end
end
class ArrayEmbedingSerializerTest < ActionController::TestCase
def setup
super
@association = UserSerializer._associations[:profile]
@old_association = @association.dup
end
def teardown
super
UserSerializer._associations[:profile] = @old_association
end
class MyController < ActionController::Base
def initialize(*)
super
@user = User.new({ name: 'Name 1', email: 'mail@server.com', gender: 'M' })
end
attr_reader :user
def render_array_embeding_in_root
render json: [@user]
end
end
tests MyController
def test_render_array_embeding_in_root
@association.embed = :ids
@association.embed_in_root = true
get :render_array_embeding_in_root
assert_equal 'application/json', @response.content_type
assert_equal("{\"my\":[{\"name\":\"Name 1\",\"email\":\"mail@server.com\",\"profile_id\":#{@controller.user.profile.object_id}}],\"profiles\":[{\"name\":\"N1\",\"description\":\"D1\"}]}", @response.body)
end
end
end
end

View File

@ -1,71 +0,0 @@
require 'test_helper'
module ActionController
module SerializationsAssertions
class RenderSerializerTest < ActionController::TestCase
class MyController < ActionController::Base
def render_using_serializer
render json: Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
end
def render_text
render text: 'ok'
end
def render_template
prepend_view_path "./test/fixtures"
render template: "template"
end
end
tests MyController
def test_supports_specifying_serializers_with_a_serializer_class
get :render_using_serializer
assert_serializer ProfileSerializer
end
def test_supports_specifying_serializers_with_a_regexp
get :render_using_serializer
assert_serializer %r{\AProfile.+\Z}
end
def test_supports_specifying_serializers_with_a_string
get :render_using_serializer
assert_serializer 'ProfileSerializer'
end
def test_supports_specifying_serializers_with_a_symbol
get :render_using_serializer
assert_serializer :profile_serializer
end
def test_supports_specifying_serializers_with_a_nil
get :render_text
assert_serializer nil
end
def test_raises_descriptive_error_message_when_serializer_was_not_rendered
get :render_using_serializer
e = assert_raise ActiveSupport::TestCase::Assertion do
assert_serializer 'PostSerializer'
end
assert_match 'expecting <"PostSerializer"> but rendering with <["ProfileSerializer"]>', e.message
end
def test_raises_argument_error_when_asserting_with_invalid_object
get :render_using_serializer
e = assert_raise ArgumentError do
assert_serializer Hash
end
assert_match 'assert_serializer only accepts a String, Symbol, Regexp, ActiveModel::Serializer, or nil', e.message
end
def test_does_not_overwrite_notification_subscriptions
get :render_template
assert_template "template"
end
end
end
end

View File

@ -1,94 +0,0 @@
require 'test_helper'
require 'fixtures/active_record'
module ActiveModel
class Serializer
class ActiveRecordTest < Minitest::Test
def setup
@post = ARPost.first
end
def test_serialization_embedding_objects
post_serializer = ARPostSerializer.new(@post)
assert_equal({
'ar_post' => {
title: 'New post', body: 'A body!!!',
ar_comments: [{ body: 'what a dumb post', ar_tags: [{ name: 'happy' }, { name: 'whiny' }] },
{ body: 'i liked it', ar_tags: [{:name=>"happy"}, {:name=>"short"}] }],
ar_tags: [{ name: 'short' }, { name: 'whiny' }],
ar_section: { 'name' => 'ruby' }
}
}, post_serializer.as_json)
end
def test_serialization_embedding_ids
post_serializer = ARPostSerializer.new(@post)
embed(ARPostSerializer, embed: :ids) do
assert_equal({
'ar_post' => {
title: 'New post', body: 'A body!!!',
'ar_comment_ids' => [1, 2],
'ar_tag_ids' => [1, 2],
'ar_section_id' => 1
}
}, post_serializer.as_json)
end
end
def test_serialization_embedding_ids_including_in_root
post_serializer = ARPostSerializer.new(@post)
embed(ARPostSerializer, embed: :ids, embed_in_root: true) do
embed(ARCommentSerializer, embed: :ids, embed_in_root: true) do
assert_equal({
'ar_post' => {
title: 'New post', body: 'A body!!!',
'ar_comment_ids' => [1, 2],
'ar_tag_ids' => [1, 2],
'ar_section_id' => 1
},
'ar_comments' => [{ body: 'what a dumb post', 'ar_tag_ids' => [3, 2] },
{ body: 'i liked it', 'ar_tag_ids' => [3, 1] }],
'ar_tags' => [{ name: 'happy' }, { name: 'whiny' }, { name: 'short' }],
'ar_sections' => [{ 'name' => 'ruby' }]
}, post_serializer.as_json)
end
end
end
def test_serialization_embedding_ids_in_common_root_key
post_serializer = AREmbeddedSerializer.new(@post)
embed(AREmbeddedSerializer, embed: :ids, embed_in_root: true, embed_in_root_key: :linked) do
embed(ARCommentSerializer, embed: :ids, embed_in_root: true, embed_in_root_key: :linked) do
assert_equal({
'ar_tags' => [{ name: 'short' },
{ name: 'whiny' },
{ name: 'happy' }],
'ar_comments' => [{ body: 'what a dumb post', 'ar_tag_ids' => [3, 2] },
{ body: 'i liked it', 'ar_tag_ids' => [3, 1] }]
}, post_serializer.as_json[:linked])
end
end
end
private
def embed(serializer_class, options = {})
old_assocs = Hash[serializer_class._associations.to_a.map { |(name, association)| [name, association.dup] }]
serializer_class._associations.each_value do |association|
association.embed = options[:embed]
association.embed_in_root = options[:embed_in_root]
association.embed_in_root_key = options[:embed_in_root_key]
end
yield
ensure
serializer_class._associations = old_assocs
end
end
end
end

View File

@ -1,26 +0,0 @@
require 'test_helper'
require 'rails'
require 'active_model/serializer/railtie'
require 'test_app'
class ResourceGeneratorTest < Rails::Generators::TestCase
destination File.expand_path('../../../tmp', __FILE__)
setup :prepare_destination, :copy_routes
tests Rails::Generators::ResourceGenerator
arguments %w(account)
def test_serializer_file_is_generated
run_generator
assert_file 'app/serializers/account_serializer.rb', /class AccountSerializer < ActiveModel::Serializer/
end
private
def copy_routes
config_dir = File.join(destination_root, 'config')
FileUtils.mkdir_p(config_dir)
File.write(File.join(config_dir, 'routes.rb'), 'Rails.application.routes.draw { }')
end
end

View File

@ -1,64 +0,0 @@
require 'test_helper'
require 'rails'
require 'active_model/serializer/railtie'
require 'test_app'
class ScaffoldControllerGeneratorTest < Rails::Generators::TestCase
destination File.expand_path('../../../tmp', __FILE__)
setup :prepare_destination
tests Rails::Generators::ScaffoldControllerGenerator
arguments %w(account name:string description:text business:references)
def test_generated_controller
return true if Rails::VERSION::MAJOR < 4
run_generator
assert_file 'app/controllers/accounts_controller.rb' do |content|
assert_instance_method :index, content do |m|
assert_match /@accounts = Account\.all/, m
assert_match /format.html/, m
assert_match /format.json \{ render json: @accounts \}/, m
end
assert_instance_method :show, content do |m|
assert_match /format.html/, m
assert_match /format.json \{ render json: @account \}/, m
end
assert_instance_method :new, content do |m|
assert_match /@account = Account\.new/, m
end
assert_instance_method :edit, content do |m|
assert m.blank?
end
assert_instance_method :create, content do |m|
assert_match /@account = Account\.new\(account_params\)/, m
assert_match /@account\.save/, m
assert_match /format\.html \{ redirect_to @account, notice: 'Account was successfully created\.' \}/, m
assert_match /format\.json \{ render json: @account, status: :created \}/, m
assert_match /format\.html \{ render action: 'new' \}/, m
assert_match /format\.json \{ render json: @account\.errors, status: :unprocessable_entity \}/, m
end
assert_instance_method :update, content do |m|
assert_match /format\.html \{ redirect_to @account, notice: 'Account was successfully updated\.' \}/, m
assert_match /format\.json \{ head :no_content \}/, m
assert_match /format\.html \{ render action: 'edit' \}/, m
assert_match /format\.json \{ render json: @account.errors, status: :unprocessable_entity \}/, m
end
assert_instance_method :destroy, content do |m|
assert_match /@account\.destroy/, m
assert_match /format\.html { redirect_to accounts_url \}/, m
assert_match /format\.json \{ head :no_content \}/, m
end
assert_match(/def account_params/, content)
assert_match(/params\.require\(:account\)\.permit\(:name, :description, :business_id\)/, content)
end
end
end

View File

@ -1,41 +0,0 @@
require 'test_helper'
require 'rails'
require 'active_model/serializer/railtie'
require 'test_app'
class SerializerGeneratorTest < Rails::Generators::TestCase
destination File.expand_path('../../../tmp', __FILE__)
setup :prepare_destination
tests Rails::Generators::SerializerGenerator
arguments %w(account name:string description:text business:references)
def test_generates_a_serializer_with_attributes_and_associations
run_generator
assert_file 'app/serializers/account_serializer.rb', /class AccountSerializer < ActiveModel::Serializer/ do |serializer|
assert_match(/attributes :id, :name, :description/, serializer)
assert_match(/has_one :business/, serializer)
end
end
def test_generates_a_namespaced_serializer
run_generator ['admin/account']
assert_file 'app/serializers/admin/account_serializer.rb', /class Admin::AccountSerializer < ActiveModel::Serializer/
end
def test_uses_application_serializer_if_one_exists
Object.const_set(:ApplicationSerializer, Class.new)
run_generator
assert_file 'app/serializers/account_serializer.rb', /class AccountSerializer < ApplicationSerializer/
ensure
Object.send :remove_const, :ApplicationSerializer
end
def test_uses_given_parent
Object.const_set(:ApplicationSerializer, Class.new)
run_generator ['Account', '--parent=MySerializer']
assert_file 'app/serializers/account_serializer.rb', /class AccountSerializer < MySerializer/
ensure
Object.send :remove_const, :ApplicationSerializer
end
end

View File

@ -1,14 +0,0 @@
class TestApp < Rails::Application
if Rails.version.to_s.first >= '4'
config.eager_load = false
config.secret_key_base = 'abc123'
end
config.after_initialize do
Rails.application.routes.default_url_options = { host: 'http://example.com' }
end
# Set up a logger to avoid creating a log directory on every run.
config.logger = Logger.new(nil)
end
TestApp.initialize!

View File

@ -1,24 +0,0 @@
require 'bundler/setup'
require 'minitest/autorun'
require 'active_model_serializers'
require 'fixtures/poro'
# Ensure backward compatibility with Minitest 4
Minitest::Test = MiniTest::Unit::TestCase unless defined?(Minitest::Test)
module TestHelper
Routes = ActionDispatch::Routing::RouteSet.new
Routes.draw do
get ':controller(/:action(/:id))'
get ':controller(/:action)'
end
ActionController::Base.send :include, Routes.url_helpers
ActionController::Base.send :include, ActionController::Serialization
end
ActionController::TestCase.class_eval do
def setup
@routes = TestHelper::Routes
end
end

View File

@ -1,18 +0,0 @@
require 'test_helper'
module ActiveModel
class ArraySerializer
class ExceptTest < Minitest::Test
def test_array_serializer_pass_except_to_items_serializers
array = [Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }),
Profile.new({ name: 'Name 2', description: 'Description 2', comments: 'Comments 2' })]
serializer = ArraySerializer.new(array, except: [:description])
expected = [{ name: 'Name 1' },
{ name: 'Name 2' }]
assert_equal expected, serializer.serializable_array
end
end
end
end

View File

@ -1,18 +0,0 @@
require 'test_helper'
module ActiveModel
class ArraySerializer
class KeyFormatTest < Minitest::Test
def test_array_serializer_pass_options_to_items_serializers
array = [WebLog.new({ name: 'Name 1', display_name: 'Display Name 1'}),
WebLog.new({ name: 'Name 2', display_name: 'Display Name 2'})]
serializer = ArraySerializer.new(array, key_format: :lower_camel)
expected = [{ name: 'Name 1', displayName: 'Display Name 1' },
{ name: 'Name 2', displayName: 'Display Name 2' }]
assert_equal expected, serializer.serializable_array
end
end
end
end

View File

@ -1,53 +0,0 @@
require 'test_helper'
require 'active_model/serializer'
module ActiveModel
class ArraySerializer
class MetaTest < Minitest::Test
def setup
@profile1 = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
@profile2 = Profile.new({ name: 'Name 2', description: 'Description 2', comments: 'Comments 2' })
@serializer = ArraySerializer.new([@profile1, @profile2], root: 'profiles')
end
def test_meta
@serializer.meta = { total: 10 }
assert_equal({
'profiles' => [
{
name: 'Name 1',
description: 'Description 1'
}, {
name: 'Name 2',
description: 'Description 2'
}
],
meta: {
total: 10
}
}, @serializer.as_json)
end
def test_meta_using_meta_key
@serializer.meta_key = :my_meta
@serializer.meta = { total: 10 }
assert_equal({
'profiles' => [
{
name: 'Name 1',
description: 'Description 1'
}, {
name: 'Name 2',
description: 'Description 2'
}
],
my_meta: {
total: 10
}
}, @serializer.as_json)
end
end
end
end

View File

@ -1,18 +0,0 @@
require 'test_helper'
module ActiveModel
class ArraySerializer
class OnlyTest < Minitest::Test
def test_array_serializer_pass_only_to_items_serializers
array = [Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }),
Profile.new({ name: 'Name 2', description: 'Description 2', comments: 'Comments 2' })]
serializer = ArraySerializer.new(array, only: [:name])
expected = [{ name: 'Name 1' },
{ name: 'Name 2' }]
assert_equal expected, serializer.serializable_array
end
end
end
end

View File

@ -1,16 +0,0 @@
require 'test_helper'
module ActiveModel
class ArraySerializer
class OptionsTest < Minitest::Test
def test_custom_options_are_accessible_from_serializer
array = [Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }),
Profile.new({ name: 'Name 2', description: 'Description 2', comments: 'Comments 2' })]
serializer = ArraySerializer.new(array, only: [:name], context: {foo: :bar})
assert_equal({foo: :bar}, serializer.context)
end
end
end
end

View File

@ -1,102 +0,0 @@
require 'test_helper'
module ActiveModel
class ArraySerializer
class RootAsOptionTest < Minitest::Test
def setup
@old_root = ArraySerializer._root
@profile1 = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
@profile2 = Profile.new({ name: 'Name 2', description: 'Description 2', comments: 'Comments 2' })
@serializer = ArraySerializer.new([@profile1, @profile2], root: :initialize)
end
def teardown
ArraySerializer._root = @old_root
end
def test_root_is_not_displayed_using_serializable_array
assert_equal([
{ name: 'Name 1', description: 'Description 1' },
{ name: 'Name 2', description: 'Description 2' }
], @serializer.serializable_array)
end
def test_root_using_as_json
assert_equal({
initialize: [
{ name: 'Name 1', description: 'Description 1' },
{ name: 'Name 2', description: 'Description 2' }
]
}, @serializer.as_json)
end
def test_root_as_argument_takes_precedence
assert_equal({
argument: [
{ name: 'Name 1', description: 'Description 1' },
{ name: 'Name 2', description: 'Description 2' }
]
}, @serializer.as_json(root: :argument))
end
def test_using_false_root_in_initialize_takes_precedence
ArraySerializer._root = 'root'
@serializer = ArraySerializer.new([@profile1, @profile2], root: false)
assert_equal([
{ name: 'Name 1', description: 'Description 1' },
{ name: 'Name 2', description: 'Description 2' }
], @serializer.as_json)
end
end
class RootInSerializerTest < Minitest::Test
def setup
@old_root = ArraySerializer._root
ArraySerializer._root = :in_serializer
@profile1 = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
@profile2 = Profile.new({ name: 'Name 2', description: 'Description 2', comments: 'Comments 2' })
@serializer = ArraySerializer.new([@profile1, @profile2])
@rooted_serializer = ArraySerializer.new([@profile1, @profile2], root: :initialize)
end
def teardown
ArraySerializer._root = @old_root
end
def test_root_is_not_displayed_using_serializable_hash
assert_equal([
{ name: 'Name 1', description: 'Description 1' },
{ name: 'Name 2', description: 'Description 2' }
], @serializer.serializable_array)
end
def test_root_using_as_json
assert_equal({
in_serializer: [
{ name: 'Name 1', description: 'Description 1' },
{ name: 'Name 2', description: 'Description 2' }
]
}, @serializer.as_json)
end
def test_root_in_initializer_takes_precedence
assert_equal({
initialize: [
{ name: 'Name 1', description: 'Description 1' },
{ name: 'Name 2', description: 'Description 2' }
]
}, @rooted_serializer.as_json)
end
def test_root_as_argument_takes_precedence
assert_equal({
argument: [
{ name: 'Name 1', description: 'Description 1' },
{ name: 'Name 2', description: 'Description 2' }
]
}, @rooted_serializer.as_json(root: :argument))
end
end
end
end

View File

@ -1,24 +0,0 @@
require 'test_helper'
module ActiveModel
class ArraySerializer
class ScopeTest < Minitest::Test
def test_array_serializer_pass_options_to_items_serializers
array = [Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }),
Profile.new({ name: 'Name 2', description: 'Description 2', comments: 'Comments 2' })]
serializer = ArraySerializer.new(array, scope: current_user)
expected = [{ name: 'Name 1', description: 'Description 1 - user' },
{ name: 'Name 2', description: 'Description 2 - user' }]
assert_equal expected, serializer.serializable_array
end
private
def current_user
'user'
end
end
end
end

View File

@ -1,216 +0,0 @@
require 'test_helper'
module ActiveModel
class ArraySerializer
class BasicObjectsSerializationTest < Minitest::Test
def setup
array = [1, 2, 3]
@serializer = Serializer.serializer_for(array).new(array)
end
def test_serializer_for_array_returns_appropriate_type
assert_kind_of ActiveModel::ArraySerializer, @serializer
end
def test_array_serializer_serializes_simple_objects
assert_equal [1, 2, 3], @serializer.serializable_array
assert_equal [1, 2, 3], @serializer.as_json
end
end
class CustomArraySerializerSupport < Minitest::Test
def setup
Object.const_set(:ArraySerializer, Class.new)
array = [1, 2, 3]
@serializer_class = Serializer.serializer_for(array)
end
def teardown
Object.send(:remove_const, :ArraySerializer)
end
def test_serializer_for_array_returns_appropriate_type
assert_equal ::ArraySerializer, @serializer_class
end
end
class CustomSerializerClassTest < Minitest::Test
def setup
Object.const_set(:CustomSerializer, Class.new)
end
def teardown
Object.send(:remove_const, :CustomSerializer)
end
def test_serializer_for_array_returns_appropriate_type
object = {}
def object.serializer_class; CustomSerializer; end
assert_equal CustomSerializer, Serializer.serializer_for(object)
end
end
class ModelSerializationTest < Minitest::Test
def test_array_serializer_serializes_models
array = [Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }),
Profile.new({ name: 'Name 2', description: 'Description 2', comments: 'Comments 2' })]
serializer = ArraySerializer.new(array)
expected = [{ name: 'Name 1', description: 'Description 1' },
{ name: 'Name 2', description: 'Description 2' }]
assert_equal expected, serializer.serializable_array
assert_equal expected, serializer.as_json
end
def test_array_serializers_each_serializer
array = [::Model.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }),
::Model.new({ name: 'Name 2', description: 'Description 2', comments: 'Comments 2' })]
serializer = ArraySerializer.new(array, each_serializer: ProfileSerializer)
expected = [{ name: 'Name 1', description: 'Description 1' },
{ name: 'Name 2', description: 'Description 2' }]
assert_equal expected, serializer.serializable_array
assert_equal expected, serializer.as_json
end
def test_associated_objects_of_multiple_instances_embedded_in_root
@association = PostSerializer._associations[:comments]
@old_association = @association.dup
@association.embed = :ids
@association.embed_in_root = true
@post1 = Post.new({ title: 'Title 1', body: 'Body 1', date: '1/1/2000' })
@post2 = Post.new({ title: 'Title 2', body: 'Body 2', date: '1/1/2000' })
class << @post2
attr_writer :comments
end
@post2.comments = [
Comment.new(content: 'C3'),
Comment.new(content: 'C4')
]
@serializer = ArraySerializer.new([@post1, @post2], root: :posts)
assert_equal({
posts: [
{title: "Title 1", body: "Body 1", "comment_ids" => @post1.comments.map(&:object_id) },
{title: "Title 2", body: "Body 2", "comment_ids" => @post2.comments.map(&:object_id) }
],
'comments' => [
{content: "C1"},
{content: "C2"},
{content: "C3"},
{content: "C4"}
]
}, @serializer.as_json)
ensure
PostSerializer._associations[:comments] = @old_association
end
def test_embed_object_for_has_one_association_with_nil_value
@association = UserSerializer._associations[:profile]
@old_association = @association.dup
@association.embed = :objects
@user1 = User.new({ name: 'User 1', email: 'email1@server.com' })
@user2 = User.new({ name: 'User 2', email: 'email2@server.com' })
class << @user1
def profile
nil
end
end
class << @user2
def profile
@profile ||= Profile.new(name: 'Name 1', description: 'Desc 1')
end
end
@serializer = ArraySerializer.new([@user1, @user2]) #, root: :posts)
assert_equal([
{ name: "User 1", email: "email1@server.com", profile: nil },
{ name: "User 2", email: "email2@server.com", profile: { name: 'Name 1', description: 'Desc 1' } }
], @serializer.as_json)
ensure
UserSerializer._associations[:profile] = @old_association
end
def test_embed_object_in_root_for_has_one_association_with_nil_value
@association = UserSerializer._associations[:profile]
@old_association = @association.dup
@association.embed = :ids
@association.embed_in_root = true
@user1 = User.new({ name: 'User 1', email: 'email1@server.com' })
@user2 = User.new({ name: 'User 2', email: 'email2@server.com' })
class << @user1
def profile
nil
end
end
class << @user2
def profile
@profile ||= Profile.new(name: 'Name 1', description: 'Desc 1')
end
end
@serializer = ArraySerializer.new([@user1, @user2], root: :users)
assert_equal({
users: [
{ name: "User 1", email: "email1@server.com", 'profile_id' => nil },
{ name: "User 2", email: "email2@server.com", 'profile_id' => @user2.profile.object_id }
],
'profiles' => [
{ name: 'Name 1', description: 'Desc 1' }
]
}, @serializer.as_json)
ensure
UserSerializer._associations[:profile] = @old_association
end
def test_embed_object_in_root_for_has_one_association_with_all_nil_values
@association = UserSerializer._associations[:profile]
@old_association = @association.dup
@association.embed = :ids
@association.embed_in_root = true
@user1 = User.new({ name: 'User 1', email: 'email1@server.com' })
@user2 = User.new({ name: 'User 2', email: 'email2@server.com' })
class << @user1
def profile
nil
end
end
class << @user2
def profile
nil
end
end
@serializer = ArraySerializer.new([@user1, @user2], root: :users)
assert_equal({
users: [
{ name: "User 1", email: "email1@server.com", 'profile_id' => nil },
{ name: "User 2", email: "email2@server.com", 'profile_id' => nil }
]
}, @serializer.as_json)
ensure
UserSerializer._associations[:profile] = @old_association
end
end
end
end

View File

@ -1,13 +0,0 @@
require 'test_helper'
module ActiveModel
class DefaultSerializer
class Test < Minitest::Test
def test_serialize_objects
assert_equal(nil, DefaultSerializer.new(nil).serializable_object)
assert_equal(1, DefaultSerializer.new(1).serializable_object)
assert_equal('hi', DefaultSerializer.new('hi').serializable_object)
end
end
end
end

View File

@ -1,36 +0,0 @@
require 'test_helper'
module ActiveModel
class Serializer
class Association
class BuildSerializerTest < Minitest::Test
def setup
@association = Association::HasOne.new('post', serializer: PostSerializer)
@post = Post.new({ title: 'Title 1', body: 'Body 1', date: '1/1/2000' })
@user = User.new
end
def test_build_serializer_for_array_called_twice
2.times do
serializer = @association.build_serializer(@post)
assert_instance_of(PostSerializer, serializer)
end
end
def test_build_serializer_from_in_a_namespace
assoc = Association::HasOne.new('profile')
serializer = TestNamespace::UserSerializer.new(@user).build_serializer(assoc)
assert_instance_of(TestNamespace::ProfileSerializer, serializer)
end
def test_build_serializer_with_prefix
assoc = Association::HasOne.new('profile', prefix: :short)
serializer = UserSerializer.new(@user).build_serializer(assoc)
assert_instance_of(ShortProfileSerializer, serializer)
end
end
end
end
end

View File

@ -1,49 +0,0 @@
require 'test_helper'
module ActiveModel
class Serializer
class AssociationsTest < Minitest::Test
def test_associations_inheritance
inherited_serializer_klass = Class.new(PostSerializer) do
has_many :users
end
another_inherited_serializer_klass = Class.new(PostSerializer)
assert_equal([:comments, :users],
inherited_serializer_klass._associations.keys)
assert_equal([:comments],
another_inherited_serializer_klass._associations.keys)
end
def test_multiple_nested_associations
parent = SelfReferencingUserParent.new(name: "The Parent")
child = SelfReferencingUser.new(name: "The child", parent: parent)
self_referencing_user_serializer = SelfReferencingUserSerializer.new(child)
result = self_referencing_user_serializer.as_json
expected_result = {
"self_referencing_user"=>{
:name=>"The child",
"type_id"=>child.type.object_id,
"parent_id"=>child.parent.object_id
},
"types"=>[
{
:name=>"N1",
},
{
:name=>"N2",
}
],
"parents"=>[
{
:name=>"N1",
"type_id"=>child.parent.type.object_id,
"parent_id"=>nil
}
]
}
assert_equal(expected_result, result)
end
end
end
end

View File

@ -1,57 +0,0 @@
require 'test_helper'
module ActiveModel
class Serializer
class AttributesTest < Minitest::Test
def setup
@profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
@profile_serializer = ProfileSerializer.new(@profile)
end
def test_attributes_definition
assert_equal([:name, :description],
@profile_serializer.class._attributes)
end
def test_attributes_serialization_using_serializable_hash
assert_equal({
name: 'Name 1', description: 'Description 1'
}, @profile_serializer.serializable_hash)
end
def test_attributes_serialization_using_as_json
assert_equal({
'profile' => { name: 'Name 1', description: 'Description 1' }
}, @profile_serializer.as_json)
end
def test_attributes_inheritance
inherited_serializer_klass = Class.new(ProfileSerializer) do
attributes :comments
end
another_inherited_serializer_klass = Class.new(ProfileSerializer)
assert_equal([:name, :description, :comments],
inherited_serializer_klass._attributes)
assert_equal([:name, :description],
another_inherited_serializer_klass._attributes)
end
def tests_query_attributes_strip_question_mark
model = Class.new(::Model) do
def strip?
true
end
end
serializer = Class.new(ActiveModel::Serializer) do
attributes :strip?
end
actual = serializer.new(model.new).as_json
assert_equal({ strip: true }, actual)
end
end
end
end

View File

@ -1,91 +0,0 @@
require 'test_helper'
module ActiveModel
class Serializer
class Config
class Test < Minitest::Test
def test_config_const_is_an_instance_of_config
assert_kind_of Config, CONFIG
end
def test_config_instance
config = Config.new
config.setting1 = 'value1'
assert_equal 'value1', config.setting1
end
def test_each_config
config = Config.new
config.setting1 = 'value1'
config.setting2 = 'value2'
actual = {}
config.each do |k, v|
actual[k] = v
end
assert_equal({ 'setting1' => 'value1', 'setting2' => 'value2' }, actual)
end
end
class ConfigTest < Minitest::Test
def test_setup
Serializer.setup do |config|
config.a = 'v1'
config.b = 'v2'
end
assert_equal 'v1', CONFIG.a
assert_equal 'v2', CONFIG.b
ensure
CONFIG.clear
end
def test_config_accessors
Serializer.setup do |config|
config.foo = 'v1'
config.bar = 'v2'
end
assert_equal 'v1', CONFIG.foo
assert_equal 'v2', CONFIG.bar
ensure
CONFIG.clear
end
def test_acessor_when_nil
assert_nil CONFIG.foo
CONFIG.foo = 1
assert_equal 1, CONFIG.foo
assert_nil CONFIG.bar
end
end
class ApplyConfigTest < Minitest::Test
def test_apply_config_to_associations
CONFIG.embed = :ids
CONFIG.embed_in_root = true
CONFIG.key_format = :lower_camel
association = PostSerializer._associations[:comments]
old_association = association.dup
association.send :initialize, association.name, association.options
assert association.embed_ids?
assert !association.embed_objects?
assert association.embed_in_root
assert_equal :lower_camel, association.key_format
assert_equal 'post', PostSerializer.root_name
CONFIG.plural_default_root = true
assert_equal 'posts', PostSerializer.root_name
ensure
PostSerializer._associations[:comments] = old_association
CONFIG.clear
end
end
end
end
end

View File

@ -1,69 +0,0 @@
require 'test_helper'
module ActiveModel
class Serializer
class FilterOptionsTest < Minitest::Test
def setup
@profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
end
def test_only_option
@profile_serializer = ProfileSerializer.new(@profile, only: :name)
assert_equal({
'profile' => { name: 'Name 1' }
}, @profile_serializer.as_json)
end
def test_except_option
@profile_serializer = ProfileSerializer.new(@profile, except: :comments)
assert_equal({
'profile' => { name: 'Name 1', description: 'Description 1' }
}, @profile_serializer.as_json)
end
end
class FilterAttributesTest < Minitest::Test
def setup
@profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
@profile_serializer = ProfileSerializer.new(@profile)
@profile_serializer.instance_eval do
def filter(keys)
keys - [:description]
end
end
end
def test_filtered_attributes_serialization
assert_equal({
'profile' => { name: 'Name 1' }
}, @profile_serializer.as_json)
end
end
class FilterAssociationsTest < Minitest::Test
def setup
@association = PostSerializer._associations[:comments]
@old_association = @association.dup
@association.embed = :ids
@association.embed_in_root = true
@post = Post.new({ title: 'Title 1', body: 'Body 1', date: '1/1/2000' })
@post_serializer = PostSerializer.new(@post)
@post_serializer.instance_eval do
def filter(keys)
keys - [:body, :comments]
end
end
end
def teardown
PostSerializer._associations[:comments] = @old_association
end
def test_filtered_associations_serialization
assert_equal({
'post' => { title: 'Title 1' }
}, @post_serializer.as_json)
end
end
end
end

View File

@ -1,189 +0,0 @@
require 'test_helper'
module ActiveModel
class Serializer
class HasManyPolymorphicTest < ActiveModel::TestCase
def setup
@association = MailSerializer._associations[:attachments]
@old_association = @association.dup
@mail = Mail.new({ body: 'Body 1' })
@mail_serializer = MailSerializer.new(@mail)
end
def teardown
MailSerializer._associations[:attachments] = @old_association
end
def model_name(object)
object.class.to_s.demodulize.underscore.to_sym
end
def test_associations_definition
assert_equal 1, MailSerializer._associations.length
assert_kind_of Association::HasMany, @association
assert_equal true, @association.polymorphic
assert_equal 'attachments', @association.name
end
def test_associations_embedding_ids_serialization_using_serializable_hash
@association.embed = :ids
assert_equal({
body: 'Body 1',
'attachment_ids' => @mail.attachments.map do |c|
{ id: c.object_id, type: model_name(c) }
end
}, @mail_serializer.serializable_hash)
end
def test_associations_embedding_ids_serialization_using_as_json
@association.embed = :ids
assert_equal({
'mail' => {
:body => 'Body 1',
'attachment_ids' => @mail.attachments.map do |c|
{ id: c.object_id, type: model_name(c) }
end
}
}, @mail_serializer.as_json)
end
def test_associations_embedding_ids_serialization_using_serializable_hash_and_key_from_options
@association.embed = :ids
@association.key = 'key'
assert_equal({
body: 'Body 1',
'key' => @mail.attachments.map do |c|
{ id: c.object_id, type: model_name(c) }
end
}, @mail_serializer.serializable_hash)
end
def test_associations_embedding_objects_serialization_using_serializable_hash
@association.embed = :objects
assert_equal({
body: 'Body 1',
:attachments => [
{ type: :image, image: { url: 'U1' }},
{ type: :video, video: { html: 'H1' }}
]
}, @mail_serializer.serializable_hash)
end
def test_associations_embedding_objects_serialization_using_as_json
@association.embed = :objects
assert_equal({
'mail' => {
body: 'Body 1',
attachments: [
{ type: :image, image: { url: 'U1' }},
{ type: :video, video: { html: 'H1' }}
]
}
}, @mail_serializer.as_json)
end
def test_associations_embedding_nil_objects_serialization_using_as_json
@association.embed = :objects
@mail.instance_eval do
def attachments
[nil]
end
end
assert_equal({
'mail' => {
:body => 'Body 1',
:attachments => [nil]
}
}, @mail_serializer.as_json)
end
def test_associations_embedding_objects_serialization_using_serializable_hash_and_root_from_options
@association.embed = :objects
@association.embedded_key = 'root'
assert_equal({
body: 'Body 1',
'root' => [
{ type: :image, image: { url: 'U1' }},
{ type: :video, video: { html: 'H1' }}
]
}, @mail_serializer.serializable_hash)
end
def test_associations_embedding_ids_including_objects_serialization_using_serializable_hash
@association.embed = :ids
@association.embed_in_root = true
assert_equal({
body: 'Body 1',
'attachment_ids' => @mail.attachments.map do |c|
{ id: c.object_id, type: model_name(c) }
end
}, @mail_serializer.serializable_hash)
end
def test_associations_embedding_ids_including_objects_serialization_using_as_json
@association.embed = :ids
@association.embed_in_root = true
assert_equal({
'mail' => {
body: 'Body 1',
'attachment_ids' => @mail.attachments.map do |c|
{ id: c.object_id, type: model_name(c) }
end,
},
'attachments' => [
{ type: :image, image: { url: 'U1' }},
{ type: :video, video: { html: 'H1' }}
]
}, @mail_serializer.as_json)
end
def test_associations_embedding_nothing_including_objects_serialization_using_as_json
@association.embed = nil
@association.embed_in_root = true
assert_equal({
'mail' => { body: 'Body 1' },
'attachments' => [
{ type: :image, image: { url: 'U1' }},
{ type: :video, video: { html: 'H1' }}
]
}, @mail_serializer.as_json)
end
def test_associations_using_a_given_serializer
@association.embed = :ids
@association.embed_in_root = true
@association.serializer_from_options = Class.new(ActiveModel::Serializer) do
def fake
'fake'
end
attributes :fake
end
assert_equal({
'mail' => {
body: 'Body 1',
'attachment_ids' => @mail.attachments.map do |c|
{ id: c.object_id, type: model_name(c) }
end
},
'attachments' => [
{ type: :image, image: { fake: 'fake' }},
{ type: :video, video: { fake: 'fake' }}
]
}, @mail_serializer.as_json)
end
end
end
end

View File

@ -1,265 +0,0 @@
require 'test_helper'
module ActiveModel
class Serializer
class HasManyTest < Minitest::Test
def setup
@association = PostSerializer._associations[:comments]
@old_association = @association.dup
@post = Post.new({ title: 'Title 1', body: 'Body 1', date: '1/1/2000' })
@post_serializer = PostSerializer.new(@post)
end
def teardown
PostSerializer._associations[:comments] = @old_association
end
def test_associations_definition
assert_equal 1, PostSerializer._associations.length
assert_kind_of Association::HasMany, @association
assert_equal 'comments', @association.name
end
def test_associations_inheritance
inherited_serializer_klass = Class.new(PostSerializer) do
has_many :some_associations
end
another_inherited_serializer_klass = Class.new(PostSerializer)
assert_equal(PostSerializer._associations.length + 1,
inherited_serializer_klass._associations.length)
assert_equal(PostSerializer._associations.length,
another_inherited_serializer_klass._associations.length)
end
def test_associations_embedding_ids_serialization_using_serializable_hash
@association.embed = :ids
assert_equal({
title: 'Title 1', body: 'Body 1', 'comment_ids' => @post.comments.map { |c| c.object_id }
}, @post_serializer.serializable_hash)
end
def test_associations_embedding_ids_serialization_using_as_json
@association.embed = :ids
assert_equal({
'post' => { title: 'Title 1', body: 'Body 1', 'comment_ids' => @post.comments.map { |c| c.object_id } }
}, @post_serializer.as_json)
end
def test_associations_embedding_ids_serialization_using_serializable_hash_and_key_from_options
@association.embed = :ids
@association.key = 'key'
assert_equal({
title: 'Title 1', body: 'Body 1', 'key' => @post.comments.map { |c| c.object_id }
}, @post_serializer.serializable_hash)
end
def test_associations_embedding_objects_serialization_using_serializable_hash
@association.embed = :objects
assert_equal({
title: 'Title 1', body: 'Body 1', comments: [{ content: 'C1' }, { content: 'C2' }]
}, @post_serializer.serializable_hash)
end
def test_associations_embedding_objects_serialization_using_as_json
@association.embed = :objects
assert_equal({
'post' => { title: 'Title 1', body: 'Body 1', comments: [{ content: 'C1' }, { content: 'C2' }] }
}, @post_serializer.as_json)
end
def test_associations_embedding_nil_objects_serialization_using_as_json
@association.embed = :objects
@post.instance_eval do
def comments
[nil]
end
end
assert_equal({
'post' => { title: 'Title 1', body: 'Body 1', comments: [nil] }
}, @post_serializer.as_json)
end
def test_associations_embedding_objects_serialization_using_serializable_hash_and_root_from_options
@association.embed = :objects
@association.embedded_key = 'root'
assert_equal({
title: 'Title 1', body: 'Body 1', 'root' => [{ content: 'C1' }, { content: 'C2' }]
}, @post_serializer.serializable_hash)
end
def test_associations_embedding_ids_including_objects_serialization_using_serializable_hash
@association.embed = :ids
@association.embed_in_root = true
assert_equal({
title: 'Title 1', body: 'Body 1', 'comment_ids' => @post.comments.map { |c| c.object_id }
}, @post_serializer.serializable_hash)
end
def test_associations_embedding_ids_including_objects_serialization_using_as_json
@association.embed = :ids
@association.embed_in_root = true
assert_equal({
'post' => { title: 'Title 1', body: 'Body 1', 'comment_ids' => @post.comments.map { |c| c.object_id } },
'comments' => [{ content: 'C1' }, { content: 'C2' }]
}, @post_serializer.as_json)
end
def test_associations_embedding_ids_including_objects_serialization_when_invoked_from_parent_serializer
@association.embed = :ids
@association.embed_in_root = true
category = Category.new(name: 'Name 1')
category.instance_variable_set(:@posts, [@post])
category_serializer = CategorySerializer.new(category)
assert_equal({
'category' => {
name: 'Name 1',
posts: [{ title: 'Title 1', body: 'Body 1', 'comment_ids' => @post.comments.map { |c| c.object_id } }]
},
"comments" => [{ content: 'C1' }, { content: 'C2' }]
}, category_serializer.as_json)
end
def test_associations_embedding_nothing_including_objects_serialization_using_as_json
@association.embed = nil
@association.embed_in_root = true
assert_equal({
'post' => { title: 'Title 1', body: 'Body 1' },
'comments' => [{ content: 'C1' }, { content: 'C2' }]
}, @post_serializer.as_json)
end
def test_associations_using_a_given_serializer
@association.embed = :ids
@association.embed_in_root = true
@association.serializer_from_options = Class.new(Serializer) do
def content
object.read_attribute_for_serialization(:content) + '!'
end
attributes :content
end
assert_equal({
'post' => { title: 'Title 1', body: 'Body 1', 'comment_ids' => @post.comments.map { |c| c.object_id } },
'comments' => [{ content: 'C1!' }, { content: 'C2!' }]
}, @post_serializer.as_json)
end
def test_associations_embedding_ids_using_a_given_array_serializer
@association.embed = :ids
@association.embed_in_root = true
@association.serializer_from_options = Class.new(ArraySerializer) do
def serializable_object
{ my_content: ['fake'] }
end
end
assert_equal({
'post' => { title: 'Title 1', body: 'Body 1', 'comment_ids' => @post.comments.map { |c| c.object_id } },
'comments' => { my_content: ['fake'] }
}, @post_serializer.as_json)
end
def test_associations_embedding_objects_using_a_given_array_serializer
@association.serializer_from_options = Class.new(ArraySerializer) do
def serializable_object(options={})
{ my_content: ['fake'] }
end
end
assert_equal({
'post' => { title: 'Title 1', body: 'Body 1', comments: { my_content: ['fake'] } }
}, @post_serializer.as_json)
end
def test_associations_embedding_ids_including_objects_serialization_with_embed_in_root_key
@association.embed_in_root = true
@association.embed_in_root_key = :linked
@association.embed = :ids
assert_equal({
'post' => {
title: 'Title 1', body: 'Body 1',
'comment_ids' => @post.comments.map(&:object_id)
},
linked: {
'comments' => [
{ content: 'C1' },
{ content: 'C2' }
]
},
}, @post_serializer.as_json)
end
def test_associations_embedding_ids_using_embed_namespace_including_object_serialization_with_embed_in_root_key
@association.embed_in_root = true
@association.embed_in_root_key = :linked
@association.embed = :ids
@association.embed_namespace = :links
@association.key = :comments
assert_equal({
'post' => {
title: 'Title 1', body: 'Body 1',
links: {
comments: @post.comments.map(&:object_id)
}
},
linked: {
'comments' => [
{ content: 'C1' },
{ content: 'C2' }
]
},
}, @post_serializer.as_json)
end
def test_associations_embedding_objects_using_embed_namespace
@association.embed = :objects
@association.embed_namespace = :links
assert_equal({
'post' => {
title: 'Title 1', body: 'Body 1',
links: {
comments: [
{ content: 'C1' },
{ content: 'C2' }
]
}
}
}, @post_serializer.as_json)
end
def test_associations_name_key_embedding_ids_serialization_using_serializable_hash
@association = NameKeyPostSerializer._associations[:comments]
@association.embed = :ids
assert_equal({
title: 'Title 1', body: 'Body 1', 'comments' => @post.comments.map { |c| c.object_id }
}, NameKeyPostSerializer.new(@post).serializable_hash)
end
def test_associations_name_key_embedding_ids_serialization_using_as_json
@association = NameKeyPostSerializer._associations[:comments]
@association.embed = :ids
assert_equal({
'name_key_post' => { title: 'Title 1', body: 'Body 1', 'comments' => @post.comments.map { |c| c.object_id } }
}, NameKeyPostSerializer.new(@post).as_json)
end
end
end
end

View File

@ -1,27 +0,0 @@
require 'test_helper'
module ActiveModel
class Serializer
class HasOneAndHasManyTest < Minitest::Test
def setup
@post = SpecialPost.new({ title: 'T1', body: 'B1'})
@post_serializer = SpecialPostSerializer.new(@post)
end
def teardown
end
def test_side_load_has_one_and_has_many_in_same_array
assert_equal({
"post" => {
title: 'T1',
body: 'B1',
'comment_ids' => @post.comments.map { |c| c.object_id },
'special_comment_id' => @post_serializer.special_comment.object_id,
},
"comments" => [{ content: 'C1' }, { content: 'C2' }, { content: 'special' }]
}, @post_serializer.as_json(root: 'post'))
end
end
end
end

View File

@ -1,196 +0,0 @@
require 'test_helper'
module ActiveModel
class Serializer
class HasOnePolymorphicTest < ActiveModel::TestCase
def setup
@association = InterviewSerializer._associations[:attachment]
@old_association = @association.dup
@interview = Interview.new({ text: 'Text 1' })
@interview_serializer = InterviewSerializer.new(@interview)
end
def teardown
InterviewSerializer._associations[:attachment] = @old_association
end
def model_name(object)
object.class.to_s.demodulize.underscore.to_sym
end
def test_associations_definition
assert_equal 1, InterviewSerializer._associations.length
assert_kind_of Association::HasOne, @association
assert_equal true, @association.polymorphic
assert_equal 'attachment', @association.name
end
def test_associations_embedding_ids_serialization_using_serializable_hash
@association.embed = :ids
assert_equal({
text: 'Text 1',
'attachment_id' => {
type: model_name(@interview.attachment),
id: @interview.attachment.object_id
}
}, @interview_serializer.serializable_hash)
end
def test_associations_embedding_ids_serialization_using_as_json
@association.embed = :ids
assert_equal({
'interview' => {
text: 'Text 1',
'attachment_id' => {
type: model_name(@interview.attachment),
id: @interview.attachment.object_id
}
}
}, @interview_serializer.as_json)
end
def test_associations_embedding_ids_serialization_using_serializable_hash_and_key_from_options
@association.embed = :ids
@association.key = 'key'
assert_equal({
text: 'Text 1',
'key' => {
type: model_name(@interview.attachment),
id: @interview.attachment.object_id
}
}, @interview_serializer.serializable_hash)
end
def test_associations_embedding_objects_serialization_using_serializable_hash
@association.embed = :objects
assert_equal({
text: 'Text 1',
attachment: {
type: model_name(@interview.attachment),
model_name(@interview.attachment) => { url: 'U1'}
}
}, @interview_serializer.serializable_hash)
end
def test_associations_embedding_objects_serialization_using_as_json
@association.embed = :objects
assert_equal({
'interview' => {
text: 'Text 1',
attachment: {
type: model_name(@interview.attachment),
model_name(@interview.attachment) => { url: 'U1'}
}
}
}, @interview_serializer.as_json)
end
def test_associations_embedding_nil_ids_serialization_using_as_json
@association.embed = :ids
@interview.instance_eval do
def attachment
nil
end
end
assert_equal({
'interview' => { text: 'Text 1', 'attachment_id' => nil }
}, @interview_serializer.as_json)
end
def test_associations_embedding_nil_objects_serialization_using_as_json
@association.embed = :objects
@interview.instance_eval do
def attachment
nil
end
end
assert_equal({
'interview' => { text: 'Text 1', attachment: nil }
}, @interview_serializer.as_json)
end
def test_associations_embedding_objects_serialization_using_serializable_hash_and_root_from_options
@association.embed = :objects
@association.embedded_key = 'root'
assert_equal({
text: 'Text 1',
'root' => {
type: model_name(@interview.attachment),
model_name(@interview.attachment) => { url: 'U1'}
}
}, @interview_serializer.serializable_hash)
end
def test_associations_embedding_ids_including_objects_serialization_using_serializable_hash
@association.embed = :ids
@association.embed_in_root = true
assert_equal({
text: 'Text 1',
'attachment_id' => {
type: model_name(@interview.attachment),
id: @interview.attachment.object_id
}
}, @interview_serializer.serializable_hash)
end
def test_associations_embedding_ids_including_objects_serialization_using_as_json
@association.embed = :ids
@association.embed_in_root = true
assert_equal({
'interview' => {
text: 'Text 1',
'attachment_id' => {
type: model_name(@interview.attachment),
id: @interview.attachment.object_id
}
},
"attachments" => [{
type: model_name(@interview.attachment),
model_name(@interview.attachment) => {
url: 'U1'
}
}]
}, @interview_serializer.as_json)
end
def test_associations_using_a_given_serializer
@association.embed = :ids
@association.embed_in_root = true
@association.serializer_from_options = Class.new(ActiveModel::Serializer) do
def name
'fake'
end
attributes :name
end
assert_equal({
'interview' => {
text: 'Text 1',
'attachment_id' => {
type: model_name(@interview.attachment),
id: @interview.attachment.object_id
}
},
"attachments" => [{
type: model_name(@interview.attachment),
model_name(@interview.attachment) => {
name: 'fake'
}
}]
}, @interview_serializer.as_json)
end
end
end
end

View File

@ -1,253 +0,0 @@
require 'test_helper'
module ActiveModel
class Serializer
class HasOneTest < Minitest::Test
def setup
@association = UserSerializer._associations[:profile]
@old_association = @association.dup
@user = User.new({ name: 'Name 1', email: 'mail@server.com', gender: 'M' })
@user_serializer = UserSerializer.new(@user)
end
def teardown
UserSerializer._associations[:profile] = @old_association
end
def test_associations_definition
assert_equal 1, UserSerializer._associations.length
assert_kind_of Association::HasOne, @association
assert_equal 'profile', @association.name
end
def test_associations_embedding_ids_serialization_using_serializable_hash
@association.embed = :ids
assert_equal({
name: 'Name 1', email: 'mail@server.com', 'profile_id' => @user.profile.object_id
}, @user_serializer.serializable_hash)
end
def test_associations_embedding_ids_serialization_using_as_json
@association.embed = :ids
assert_equal({
'user' => { name: 'Name 1', email: 'mail@server.com', 'profile_id' => @user.profile.object_id }
}, @user_serializer.as_json)
end
def test_associations_embedding_ids_serialization_using_serializable_hash_and_key_from_options
@association.embed = :ids
@association.key = 'key'
assert_equal({
name: 'Name 1', email: 'mail@server.com', 'key' => @user.profile.object_id
}, @user_serializer.serializable_hash)
end
def test_associations_embedding_objects_serialization_using_serializable_hash
@association.embed = :objects
assert_equal({
name: 'Name 1', email: 'mail@server.com', profile: { name: 'N1', description: 'D1' }
}, @user_serializer.serializable_hash)
end
def test_associations_embedding_objects_serialization_using_as_json
@association.embed = :objects
assert_equal({
'user' => { name: 'Name 1', email: 'mail@server.com', profile: { name: 'N1', description: 'D1' } }
}, @user_serializer.as_json)
end
def test_associations_embedding_nil_ids_serialization_using_as_json
@association.embed = :ids
@user.instance_eval do
def profile
nil
end
end
assert_equal({
'user' => { name: 'Name 1', email: 'mail@server.com', 'profile_id' => nil }
}, @user_serializer.as_json)
end
def test_associations_embedding_nil_objects_serialization_using_as_json
@association.embed = :objects
@user.instance_eval do
def profile
nil
end
end
assert_equal({
'user' => { name: 'Name 1', email: 'mail@server.com', profile: nil }
}, @user_serializer.as_json)
end
def test_associations_embedding_objects_serialization_using_serializable_hash_and_root_from_options
@association.embed = :objects
@association.embedded_key = 'root'
assert_equal({
name: 'Name 1', email: 'mail@server.com', 'root' => { name: 'N1', description: 'D1' }
}, @user_serializer.serializable_hash)
end
def test_associations_embedding_ids_including_objects_serialization_using_serializable_hash
@association.embed = :ids
@association.embed_in_root = true
assert_equal({
name: 'Name 1', email: 'mail@server.com', 'profile_id' => @user.profile.object_id
}, @user_serializer.serializable_hash)
end
def test_associations_embedding_nil_ids_including_objects_serialization_using_as_json
@association.embed = :ids
@association.embed_in_root = true
@user.instance_eval do
def profile
nil
end
end
assert_equal({
'user' => { name: 'Name 1', email: 'mail@server.com', 'profile_id' => nil },
'profiles' => []
}, @user_serializer.as_json)
end
def test_associations_embedding_ids_including_objects_serialization_using_as_json
@association.embed = :ids
@association.embed_in_root = true
assert_equal({
'user' => { name: 'Name 1', email: 'mail@server.com', 'profile_id' => @user.profile.object_id },
'profiles' => [{ name: 'N1', description: 'D1' }]
}, @user_serializer.as_json)
end
def test_associations_embedding_ids_including_objects_serialization_when_invoked_from_parent_serializer
@association.embed = :ids
@association.embed_in_root = true
user_info = UserInfo.new
user_info.instance_variable_set(:@user, @user)
user_info_serializer = UserInfoSerializer.new(user_info)
assert_equal({
'user_info' => { user: { name: 'Name 1', email: 'mail@server.com', 'profile_id' => @user.profile.object_id } },
'profiles' => [{ name: 'N1', description: 'D1' }]
}, user_info_serializer.as_json)
end
def test_associations_embedding_ids_using_a_given_serializer
@association.embed = :ids
@association.embed_in_root = true
@association.serializer_from_options = Class.new(Serializer) do
def name
'fake'
end
attributes :name
end
assert_equal({
'user' => { name: 'Name 1', email: 'mail@server.com', 'profile_id' => @user.profile.object_id },
'profiles' => [{ name: 'fake' }]
}, @user_serializer.as_json)
end
def test_associations_embedding_objects_using_a_given_serializer
@association.serializer_from_options = Class.new(Serializer) do
def name
'fake'
end
attributes :name
end
assert_equal({
'user' => { name: 'Name 1', email: 'mail@server.com', profile: { name: 'fake' } }
}, @user_serializer.as_json)
end
def test_associations_embedding_objects_with_nil_values
user_info = UserInfo.new
user_info.instance_eval do
def user
nil
end
end
user_info_serializer = UserInfoSerializer.new(user_info)
assert_equal({
'user_info' => { user: nil }
}, user_info_serializer.as_json)
end
def test_associations_embedding_ids_using_embed_namespace
@association.embed_namespace = :links
@association.embed = :ids
@association.key = :profile
assert_equal({
'user' => {
name: 'Name 1', email: 'mail@server.com',
links: {
profile: @user.profile.object_id
}
}
}, @user_serializer.as_json)
end
def test_asociations_embedding_objects_using_embed_namespace
@association.embed_namespace = :links
@association.embed = :objects
assert_equal({
'user' => {
name: 'Name 1', email: 'mail@server.com',
links: {
profile: { name: 'N1', description: 'D1' }
}
}
}, @user_serializer.as_json)
end
def test_associations_embedding_ids_using_embed_namespace_and_embed_in_root_key
@association.embed_in_root = true
@association.embed_in_root_key = :linked
@association.embed = :ids
assert_equal({
'user' => {
name: 'Name 1', email: 'mail@server.com', 'profile_id' => @user.profile.object_id
},
linked: {
'profiles' => [ { name: 'N1', description: 'D1' } ]
}
}, @user_serializer.as_json)
end
def test_associations_name_key_embedding_ids_serialization_using_serializable_hash
@association = NameKeyUserSerializer._associations[:profile]
@association.embed = :ids
assert_equal({
name: 'Name 1', email: 'mail@server.com', 'profile' => @user.profile.object_id
}, NameKeyUserSerializer.new(@user).serializable_hash)
end
def test_associations_name_key_embedding_ids_serialization_using_as_json
@association = NameKeyUserSerializer._associations[:profile]
@association.embed = :ids
assert_equal({
'name_key_user' => { name: 'Name 1', email: 'mail@server.com', 'profile' => @user.profile.object_id }
}, NameKeyUserSerializer.new(@user).as_json)
end
end
end
end

View File

@ -1,25 +0,0 @@
require 'test_helper'
module ActiveModel
class Serializer
class KeyFormatTest < Minitest::Test
def test_lower_camel_format_option
object = WebLog.new({ name: 'Name 1', display_name: 'Display Name 1'})
serializer = WebLogSerializer.new(object, key_format: :lower_camel)
expected = { name: 'Name 1', displayName: 'Display Name 1' }
assert_equal expected, serializer.serializable_object
end
def test_lower_camel_format_serializer
object = WebLog.new({ name: 'Name 1', display_name: 'Display Name 1'})
serializer = WebLogLowerCamelSerializer.new(object)
expected = { name: 'Name 1', displayName: 'Display Name 1' }
assert_equal expected, serializer.serializable_object
end
end
end
end

View File

@ -1,39 +0,0 @@
require 'test_helper'
module ActiveModel
class Serializer
class MetaTest < Minitest::Test
def setup
@profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
end
def test_meta
profile_serializer = ProfileSerializer.new(@profile, root: 'profile', meta: { total: 10 })
assert_equal({
'profile' => {
name: 'Name 1',
description: 'Description 1'
},
meta: {
total: 10
}
}, profile_serializer.as_json)
end
def test_meta_using_meta_key
profile_serializer = ProfileSerializer.new(@profile, root: 'profile', meta_key: :my_meta, my_meta: { total: 10 })
assert_equal({
'profile' => {
name: 'Name 1',
description: 'Description 1'
},
my_meta: {
total: 10
}
}, profile_serializer.as_json)
end
end
end
end

View File

@ -1,42 +0,0 @@
require 'test_helper'
module ActiveModel
class Serializer
class OptionsTest < Minitest::Test
def setup
@serializer = ProfileSerializer.new(nil, context: {foo: :bar})
end
def test_custom_options_are_accessible_from_serializer
assert_equal({foo: :bar}, @serializer.context)
end
end
class SerializationOptionsTest < Minitest::Test
def setup
@profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
@profile_serializer = ProfileSerializer.new(@profile)
@profile_serializer.instance_eval do
def description
serialization_options[:force_the_description]
end
end
@category = Category.new({name: 'Category 1'})
@category_serializer = CategorySerializer.new(@category)
end
def test_filtered_attributes_serialization
forced_description = "This is a test"
assert_equal({
'profile' => { name: 'Name 1', description: forced_description }
}, @profile_serializer.as_json(force_the_description: forced_description))
end
def test_filtered_attributes_serialization_across_association
assert_equal("'T1'",
@category_serializer.as_json(highlight_keyword: 'T1')['category'][:posts][0][:title])
end
end
end
end

View File

@ -1,117 +0,0 @@
require 'test_helper'
module ActiveModel
class Serializer
class RootAsOptionTest < Minitest::Test
def setup
@old_root = ProfileSerializer._root
@profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
@serializer = ProfileSerializer.new(@profile, root: :initialize)
ProfileSerializer._root = true
end
def teardown
ProfileSerializer._root = @old_root
end
def test_root_is_not_displayed_using_serializable_hash
assert_equal({
name: 'Name 1', description: 'Description 1'
}, @serializer.serializable_hash)
end
def test_root_using_as_json
assert_equal({
initialize: {
name: 'Name 1', description: 'Description 1'
}
}, @serializer.as_json)
end
def test_root_from_serializer_name
@serializer = ProfileSerializer.new(@profile)
assert_equal({
'profile' => {
name: 'Name 1', description: 'Description 1'
}
}, @serializer.as_json)
end
def test_root_as_argument_takes_precedence
assert_equal({
argument: {
name: 'Name 1', description: 'Description 1'
}
}, @serializer.as_json(root: :argument))
end
def test_using_false_root_in_initializer_takes_precedence
ProfileSerializer._root = 'root'
@serializer = ProfileSerializer.new(@profile, root: false)
assert_equal({
name: 'Name 1', description: 'Description 1'
}, @serializer.as_json)
end
def test_root_inheritance
ProfileSerializer._root = 'profile'
inherited_serializer_klass = Class.new(ProfileSerializer)
inherited_serializer_klass._root = 'inherited_profile'
another_inherited_serializer_klass = Class.new(ProfileSerializer)
assert_equal('inherited_profile',
inherited_serializer_klass._root)
assert_equal('profile',
another_inherited_serializer_klass._root)
end
end
class RootInSerializerTest < Minitest::Test
def setup
@old_root = ProfileSerializer._root
ProfileSerializer._root = :in_serializer
profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
@serializer = ProfileSerializer.new(profile)
@rooted_serializer = ProfileSerializer.new(profile, root: :initialize)
end
def teardown
ProfileSerializer._root = @old_root
end
def test_root_is_not_displayed_using_serializable_hash
assert_equal({
name: 'Name 1', description: 'Description 1'
}, @serializer.serializable_hash)
end
def test_root_using_as_json
assert_equal({
in_serializer: {
name: 'Name 1', description: 'Description 1'
}
}, @serializer.as_json)
end
def test_root_in_initializer_takes_precedence
assert_equal({
initialize: {
name: 'Name 1', description: 'Description 1'
}
}, @rooted_serializer.as_json)
end
def test_root_as_argument_takes_precedence
assert_equal({
argument: {
name: 'Name 1', description: 'Description 1'
}
}, @rooted_serializer.as_json(root: :argument))
end
end
end
end

View File

@ -1,49 +0,0 @@
require 'test_helper'
module ActiveModel
class Serializer
class ScopeTest < Minitest::Test
def setup
@serializer = ProfileSerializer.new(nil, scope: current_user)
end
def test_scope
assert_equal('user', @serializer.scope)
end
private
def current_user
'user'
end
end
class NestedScopeTest < Minitest::Test
def setup
@association = UserSerializer._associations[:profile]
@old_association = @association.dup
@user = User.new({ name: 'Name 1', email: 'mail@server.com', gender: 'M' })
@user_serializer = UserSerializer.new(@user, scope: 'user')
end
def teardown
UserSerializer._associations[:profile] = @old_association
end
def test_scope_passed_through
@association.serializer_from_options = Class.new(Serializer) do
def name
scope
end
attributes :name
end
assert_equal({
name: 'Name 1', email: 'mail@server.com', profile: { name: 'user' }
}, @user_serializer.serializable_hash)
end
end
end
end

View File

@ -1,35 +0,0 @@
require 'test_helper'
module ActiveModel
class Serializer
class UrlHelpersTest < Minitest::Test
include Rails.application.routes.url_helpers
def setup
Object.const_set 'UserController', Class.new(ActionController::Base) do
def show
render text: 'profile'
end
end
Rails.application.routes.draw do
get '/profile/:id', as: :profile, controller: :user, action: :show
end
end
def test_url_helpers_are_available
serializer = Class.new(ActiveModel::Serializer) do
attributes :url
def url
profile_url(id: object.object_id)
end
end
profile = Profile.new
assert_equal({ url: profile_url(id: profile.object_id) },
serializer.new(profile).as_json)
end
end
end
end

View File

@ -1,50 +0,0 @@
require 'test_helper'
module ActiveModel
class SerializableTest
class InstrumentationTest < Minitest::Test
def setup
@events = []
@subscriber = ActiveSupport::Notifications.subscribe('!serialize.active_model_serializers') do |name, start, finish, id, payload|
@events << { name: name, serializer: payload[:serializer] }
end
end
def teardown
ActiveSupport::Notifications.unsubscribe(@subscriber) if defined?(@subscriber)
end
def test_instruments_default_serializer
DefaultSerializer.new(1).as_json
assert_equal [{ name: '!serialize.active_model_serializers', serializer: 'ActiveModel::DefaultSerializer' }], @events
end
def test_instruments_serializer
profile = Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1')
serializer = ProfileSerializer.new(profile)
serializer.as_json
assert_equal [{ name: '!serialize.active_model_serializers', serializer: 'ProfileSerializer' }], @events
end
def test_instruments_array_serializer
profiles = [
Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1'),
Profile.new(name: 'Name 2', description: 'Description 2', comments: 'Comments 2')
]
serializer = ArraySerializer.new(profiles)
serializer.as_json
assert_equal [
{ name: '!serialize.active_model_serializers', serializer: 'ProfileSerializer' },
{ name: '!serialize.active_model_serializers', serializer: 'ProfileSerializer' },
{ name: '!serialize.active_model_serializers', serializer: 'ActiveModel::ArraySerializer' }
], @events
end
end
end
end