Skip to content

Commit 23f03ff

Browse files
authored
Merge pull request #2016 from rails-api/prepare_release
Prepare release of 0.10.4
2 parents cd09e89 + 97b587b commit 23f03ff

File tree

18 files changed

+168
-536
lines changed

18 files changed

+168
-536
lines changed

.travis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ sudo: false
44

55
rvm:
66
- 2.1
7-
- 2.2.3
8-
- 2.3.0
7+
- 2.2.6
8+
- 2.3.3
99
- ruby-head
1010
- jruby-9.0.4.0
1111
- jruby-head

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ Fixes:
1010

1111
Misc:
1212

13+
- [#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)
14+
1315
### [v0.10.3 (2016-11-21)](https://github.com/rails-api/active_model_serializers/compare/v0.10.2...v0.10.3)
1416

1517
Fixes:

README.md

Lines changed: 142 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,14 @@ If you'd like to chat, we have a [community slack](http://amserializers.herokuap
8484
Thanks!
8585

8686
## Documentation
87+
88+
If you're reading this at https://github.com/rails-api/active_model_serializers you are
89+
reading documentation for our `master`, which may include features that have not
90+
been released yet. Please see below for the documentation relevant to you.
91+
8792
- [0.10 (master) Documentation](https://github.com/rails-api/active_model_serializers/tree/master)
88-
- [![API Docs](http://img.shields.io/badge/yard-docs-blue.svg)](http://www.rubydoc.info/gems/active_model_serializers/0.10.2)
93+
- [0.10.3 (latest release) Documentation](https://github.com/rails-api/active_model_serializers/tree/v0.10.3)
94+
- [![API Docs](http://img.shields.io/badge/yard-docs-blue.svg)](http://www.rubydoc.info/gems/active_model_serializers/0.10.3)
8995
- [Guides](docs)
9096
- [0.9 (0-9-stable) Documentation](https://github.com/rails-api/active_model_serializers/tree/0-9-stable)
9197
- [![API Docs](http://img.shields.io/badge/yard-docs-blue.svg)](http://www.rubydoc.info/github/rails-api/active_model_serializers/0-9-stable)
@@ -156,7 +162,141 @@ serializer = SomeSerializer.new(resource, serializer_options)
156162
serializer.attributes
157163
serializer.associations
158164
```
159-
See [ARCHITECTURE.md](docs/ARCHITECTURE.md) for more information.
165+
166+
## Architecture
167+
168+
This section focuses on architecture the 0.10.x version of ActiveModelSerializers. If you are interested in the architecture of the 0.8 or 0.9 versions,
169+
please refer to the [0.8 README](https://github.com/rails-api/active_model_serializers/blob/0-8-stable/README.md) or
170+
[0.9 README](https://github.com/rails-api/active_model_serializers/blob/0-9-stable/README.md).
171+
172+
The original design is also available [here](https://github.com/rails-api/active_model_serializers/blob/d72b66d4c5355b0ff0a75a04895fcc4ea5b0c65e/README.textile).
173+
174+
### ActiveModel::Serializer
175+
176+
An **`ActiveModel::Serializer`** wraps a [serializable resource](https://github.com/rails/rails/blob/4-2-stable/activemodel/lib/active_model/serialization.rb)
177+
and exposes an `attributes` method, among a few others.
178+
It allows you to specify which attributes and associations should be represented in the serializatation of the resource.
179+
It requires an adapter to transform its attributes into a JSON document; it cannot be serialized itself.
180+
It may be useful to think of it as a
181+
[presenter](http://blog.steveklabnik.com/posts/2011-09-09-better-ruby-presenters).
182+
183+
#### ActiveModel::CollectionSerializer
184+
185+
The **`ActiveModel::CollectionSerializer`** represents a collection of resources as serializers
186+
and, if there is no serializer, primitives.
187+
188+
### ActiveModelSerializers::Adapter::Base
189+
190+
The **`ActiveModelSerializeres::Adapter::Base`** describes the structure of the JSON document generated from a
191+
serializer. For example, the `Attributes` example represents each serializer as its
192+
unmodified attributes. The `JsonApi` adapter represents the serializer as a [JSON
193+
API](http://jsonapi.org/) document.
194+
195+
### ActiveModelSerializers::SerializableResource
196+
197+
The **`ActiveModelSerializers::SerializableResource`** acts to coordinate the serializer(s) and adapter
198+
to an object that responds to `to_json`, and `as_json`. It is used in the controller to
199+
encapsulate the serialization resource when rendered. However, it can also be used on its own
200+
to serialize a resource outside of a controller, as well.
201+
202+
### Primitive handling
203+
204+
Definitions: A primitive is usually a String or Array. There is no serializer
205+
defined for them; they will be serialized when the resource is converted to JSON (`as_json` or
206+
`to_json`). (The below also applies for any object with no serializer.)
207+
208+
- ActiveModelSerializers doesn't handle primitives passed to `render json:` at all.
209+
210+
Internally, if no serializer can be found in the controller, the resource is not decorated by
211+
ActiveModelSerializers.
212+
213+
- However, when a primitive value is an attribute or in a collection, it is not modified.
214+
215+
When serializing a collection and the collection serializer (CollectionSerializer) cannot
216+
identify a serializer for a resource in its collection, it throws [`:no_serializer`](https://github.com/rails-api/active_model_serializers/issues/1191#issuecomment-142327128).
217+
For example, when caught by `Reflection#build_association`, and the association value is set directly:
218+
219+
```ruby
220+
reflection_options[:virtual_value] = association_value.try(:as_json) || association_value
221+
```
222+
223+
(which is called by the adapter as `serializer.associations(*)`.)
224+
225+
### How options are parsed
226+
227+
High-level overview:
228+
229+
- For a **collection**
230+
- `:serializer` specifies the collection serializer and
231+
- `:each_serializer` specifies the serializer for each resource in the collection.
232+
- For a **single resource**, the `:serializer` option is the resource serializer.
233+
- Options are partitioned in serializer options and adapter options. Keys for adapter options are specified by
234+
[`ADAPTER_OPTION_KEYS`](https://github.com/rails-api/active_model_serializers/blob/master/lib/active_model_serializers/serializable_resource.rb#L5).
235+
The remaining options are serializer options.
236+
237+
Details:
238+
239+
1. **ActionController::Serialization**
240+
1. `serializable_resource = ActiveModelSerializers::SerializableResource.new(resource, options)`
241+
1. `options` are partitioned into `adapter_opts` and everything else (`serializer_opts`).
242+
The `adapter_opts` keys are defined in [`ActiveModelSerializers::SerializableResource::ADAPTER_OPTION_KEYS`](lib/active_model_serializers/serializable_resource.rb#L5).
243+
1. **ActiveModelSerializers::SerializableResource**
244+
1. `if serializable_resource.serializer?` (there is a serializer for the resource, and an adapter is used.)
245+
- Where `serializer?` is `use_adapter? && !!(serializer)`
246+
- Where `use_adapter?`: 'True when no explicit adapter given, or explicit value is truthy (non-nil);
247+
False when explicit adapter is falsy (nil or false)'
248+
- Where `serializer`:
249+
1. from explicit `:serializer` option, else
250+
2. implicitly from resource `ActiveModel::Serializer.serializer_for(resource)`
251+
1. A side-effect of checking `serializer` is:
252+
- The `:serializer` option is removed from the serializer_opts hash
253+
- If the `:each_serializer` option is present, it is removed from the serializer_opts hash and set as the `:serializer` option
254+
1. The serializer and adapter are created as
255+
1. `serializer_instance = serializer.new(resource, serializer_opts)`
256+
2. `adapter_instance = ActiveModel::Serializer::Adapter.create(serializer_instance, adapter_opts)`
257+
1. **ActiveModel::Serializer::CollectionSerializer#new**
258+
1. If the `serializer_instance` was a `CollectionSerializer` and the `:serializer` serializer_opts
259+
is present, then [that serializer is passed into each resource](https://github.com/rails-api/active_model_serializers/blob/a54d237e2828fe6bab1ea5dfe6360d4ecc8214cd/lib/active_model/serializer/array_serializer.rb#L14-L16).
260+
1. **ActiveModel::Serializer#attributes** is used by the adapter to get the attributes for
261+
resource as defined by the serializer.
262+
263+
(In Rails, the `options` are also passed to the `as_json(options)` or `to_json(options)`
264+
methods on the resource serialization by the Rails JSON renderer. They are, therefore, important
265+
to know about, but not part of ActiveModelSerializers.)
266+
267+
### What does a 'serializable resource' look like?
268+
269+
- An `ActiveRecord::Base` object.
270+
- Any Ruby object that passes the
271+
[Lint](http://www.rubydoc.info/github/rails-api/active_model_serializers/ActiveModel/Serializer/Lint/Tests)
272+
[code](https://github.com/rails-api/active_model_serializers/blob/master/lib/active_model/serializer/lint.rb).
273+
274+
ActiveModelSerializers provides a
275+
[`ActiveModelSerializers::Model`](https://github.com/rails-api/active_model_serializers/blob/master/lib/active_model_serializers/model.rb),
276+
which is a simple serializable PORO (Plain-Old Ruby Object).
277+
278+
`ActiveModelSerializers::Model` may be used either as a reference implementation, or in production code.
279+
280+
```ruby
281+
class MyModel < ActiveModelSerializers::Model
282+
attr_accessor :id, :name, :level
283+
end
284+
```
285+
286+
The default serializer for `MyModel` would be `MyModelSerializer` whether MyModel is an
287+
ActiveRecord::Base object or not.
288+
289+
Outside of the controller the rules are **exactly** the same as for records. For example:
290+
291+
```ruby
292+
render json: MyModel.new(level: 'awesome'), adapter: :json
293+
```
294+
295+
would be serialized the same as
296+
297+
```ruby
298+
ActiveModelSerializers::SerializableResource.new(MyModel.new(level: 'awesome'), adapter: :json).as_json
299+
```
160300

161301
## Semantic Versioning
162302

active_model_serializers.gemspec

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ Gem::Specification.new do |spec|
4242
# 'minitest'
4343
# 'thread_safe'
4444

45-
spec.add_runtime_dependency 'jsonapi', '0.1.1.beta2'
45+
spec.add_runtime_dependency 'jsonapi', '0.1.1.beta6'
46+
spec.add_runtime_dependency 'case_transform', '>= 0.2'
4647

4748
spec.add_development_dependency 'activerecord', rails_versions
4849
# arel

docs/ARCHITECTURE.md

Lines changed: 0 additions & 125 deletions
This file was deleted.

docs/README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ This is the documentation of ActiveModelSerializers, it's focused on the **0.10.
1818
- JSON API
1919
- [Schema](jsonapi/schema.md)
2020
- [Errors](jsonapi/errors.md)
21-
- [ARCHITECTURE](ARCHITECTURE.md)
2221

2322
## How to
2423

docs/general/rendering.md

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -48,26 +48,11 @@ render json: @posts, serializer: CollectionSerializer, each_serializer: PostPrev
4848

4949
## Serializing non-ActiveRecord objects
5050

51-
All serializable resources must pass the
52-
[ActiveModel::Serializer::Lint::Tests](../../lib/active_model/serializer/lint.rb#L17).
53-
54-
See the ActiveModelSerializers::Model for a base class that implements the full
55-
API for a plain-old Ruby object (PORO).
51+
See [README](../../README.md#what-does-a-serializable-resource-look-like)
5652

5753
## SerializableResource options
5854

59-
The `options` hash passed to `render` or `ActiveModelSerializers::SerializableResource.new(resource, options)`
60-
are partitioned into `serializer_opts` and `adapter_opts`. `adapter_opts` are passed to new Adapters;
61-
`serializer_opts` are passed to new Serializers.
62-
63-
The `adapter_opts` are specified in [ActiveModelSerializers::SerializableResource::ADAPTER_OPTIONS](../../lib/active_model_serializers/serializable_resource.rb#L5).
64-
The `serializer_opts` are the remaining options.
65-
66-
(In Rails, the `options` are also passed to the `as_json(options)` or `to_json(options)`
67-
methods on the resource serialization by the Rails JSON renderer. They are, therefore, important
68-
to know about, but not part of ActiveModelSerializers.)
69-
70-
See [ARCHITECTURE](../ARCHITECTURE.md) for more information.
55+
See [README](../../README.md#activemodelserializersserializableresource)
7156

7257
### adapter_opts
7358

docs/howto/add_relationship_links.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class Api::V1::UserSerializer < ActiveModel::Serializer
3737
end
3838
```
3939

40-
This will resilt in (example is in jsonapi adapter):
40+
This will result in (example is in JSONAPI adapter):
4141
```json
4242
{
4343
"data": {
@@ -69,7 +69,7 @@ class Api::V1::UserSerializer < ActiveModel::Serializer
6969
end
7070
```
7171

72-
This will resilt in (example is in jsonapi adapter):
72+
This will result in (example is in JSONAPI adapter):
7373
```json
7474
{
7575
"data": {

lib/active_model/serializer/concerns/attributes.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ def _attributes
6666
end
6767

6868
# @api private
69-
# maps attribute value to explict key name
69+
# maps attribute value to explicit key name
7070
# @see Serializer::attribute
7171
# @see FragmentCache#fragment_serializer
7272
def _attributes_keys

lib/active_model_serializers/adapter/base.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
require 'active_model_serializers/key_transform'
1+
require 'case_transform'
22

33
module ActiveModelSerializers
44
module Adapter
@@ -31,7 +31,7 @@ def self.transform(options)
3131
# @param options [Object] serializable resource options
3232
# @return [Symbol] the default transform for the adapter
3333
def self.transform_key_casing!(value, options)
34-
KeyTransform.send(transform(options), value)
34+
CaseTransform.send(transform(options), value)
3535
end
3636

3737
def self.cache_key

0 commit comments

Comments
 (0)