cheap_ams 0.10.8 → 0.10.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +33 -0
- data/.simplecov +1 -1
- data/CHANGELOG.md +1 -0
- data/Gemfile +4 -0
- data/README.md +22 -5
- data/docs/general/adapters.md +55 -2
- data/lib/action_controller/serialization.rb +3 -0
- data/lib/active_model/serializable_resource.rb +1 -1
- data/lib/active_model/serializer.rb +3 -12
- data/lib/active_model/serializer/adapter.rb +67 -6
- data/lib/active_model/serializer/adapter/flatten_json.rb +2 -9
- data/lib/active_model/serializer/adapter/fragment_cache.rb +1 -7
- data/lib/active_model/serializer/adapter/json.rb +11 -16
- data/lib/active_model/serializer/adapter/json/fragment_cache.rb +1 -10
- data/lib/active_model/serializer/adapter/json_api.rb +36 -49
- data/lib/active_model/serializer/adapter/json_api/fragment_cache.rb +1 -10
- data/lib/active_model/serializer/adapter/json_api/pagination_links.rb +1 -9
- data/lib/active_model/serializer/adapter/null.rb +1 -7
- data/lib/active_model/serializer/fieldset.rb +2 -2
- data/lib/active_model/serializer/utils.rb +35 -0
- data/lib/active_model/serializer/version.rb +1 -1
- data/test/action_controller/json_api/linked_test.rb +7 -8
- data/test/action_controller/serialization_scope_name_test.rb +1 -1
- data/test/active_record_test.rb +9 -0
- data/test/adapter/json_api/belongs_to_test.rb +3 -3
- data/test/adapter/json_api/has_many_explicit_serializer_test.rb +1 -1
- data/test/adapter/json_api/has_many_test.rb +2 -2
- data/test/adapter/json_api/has_one_test.rb +2 -2
- data/test/adapter/json_api/linked_test.rb +6 -6
- data/test/adapter_test.rb +0 -10
- data/test/serializers/adapter_for_test.rb +123 -2
- data/test/utils/include_args_to_hash_test.rb +79 -0
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 95422216cd4811b37e7e9943fc97c1f8e1984e08
|
4
|
+
data.tar.gz: 18bb09e6ba28642242e1e75092ed5250ed9456f3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c05c8d9b94ae34f70e5e4e3a017a1871da8497b9ecf281e967d73f0fc8033b39fc486e726c059b870935c52de544cc633d87979423f1241b9df9d4c2c0df4bf4
|
7
|
+
data.tar.gz: 9514e1203f2ccefe5b917538c47238d4e19687dd89ce4f6ebb6a9e03c4a83bb0c9f0c6c141f6a26086f2853d2445bb15912b308892a52bba6d1ff030de2d2aae
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -8,6 +8,39 @@ AllCops:
|
|
8
8
|
DisplayCopNames: true
|
9
9
|
DisplayStyleGuide: true
|
10
10
|
|
11
|
+
Style/IndentationConsistency:
|
12
|
+
Exclude:
|
13
|
+
- lib/active_model/serializer/adapter/flatten_json.rb
|
14
|
+
- lib/active_model/serializer/adapter/fragment_cache.rb
|
15
|
+
- lib/active_model/serializer/adapter/json.rb
|
16
|
+
- lib/active_model/serializer/adapter/json/fragment_cache.rb
|
17
|
+
- lib/active_model/serializer/adapter/json_api.rb
|
18
|
+
- lib/active_model/serializer/adapter/json_api/fragment_cache.rb
|
19
|
+
- lib/active_model/serializer/adapter/json_api/pagination_links.rb
|
20
|
+
- lib/active_model/serializer/adapter/null.rb
|
21
|
+
|
22
|
+
Style/IndentationWidth:
|
23
|
+
Exclude:
|
24
|
+
- lib/active_model/serializer/adapter/flatten_json.rb
|
25
|
+
- lib/active_model/serializer/adapter/fragment_cache.rb
|
26
|
+
- lib/active_model/serializer/adapter/json.rb
|
27
|
+
- lib/active_model/serializer/adapter/json/fragment_cache.rb
|
28
|
+
- lib/active_model/serializer/adapter/json_api.rb
|
29
|
+
- lib/active_model/serializer/adapter/json_api/fragment_cache.rb
|
30
|
+
- lib/active_model/serializer/adapter/json_api/pagination_links.rb
|
31
|
+
- lib/active_model/serializer/adapter/null.rb
|
32
|
+
|
33
|
+
Style/AccessModifierIndentation:
|
34
|
+
Exclude:
|
35
|
+
- lib/active_model/serializer/adapter/flatten_json.rb
|
36
|
+
- lib/active_model/serializer/adapter/fragment_cache.rb
|
37
|
+
- lib/active_model/serializer/adapter/json.rb
|
38
|
+
- lib/active_model/serializer/adapter/json/fragment_cache.rb
|
39
|
+
- lib/active_model/serializer/adapter/json_api.rb
|
40
|
+
- lib/active_model/serializer/adapter/json_api/fragment_cache.rb
|
41
|
+
- lib/active_model/serializer/adapter/json_api/pagination_links.rb
|
42
|
+
- lib/active_model/serializer/adapter/null.rb
|
43
|
+
|
11
44
|
Lint/NestedMethodDefinition:
|
12
45
|
Enabled: false
|
13
46
|
Exclude:
|
data/.simplecov
CHANGED
data/CHANGELOG.md
CHANGED
@@ -11,3 +11,4 @@
|
|
11
11
|
* remove root key option and split JSON adapter [@joaomdmoura]
|
12
12
|
* adds FlattenJSON as default adapter [@joaomdmoura]
|
13
13
|
* adds support for `pagination links` at top level of JsonApi adapter [@bacarini]
|
14
|
+
* adds extended format for `include` option to JSONAPI adapter [@beauby]
|
data/Gemfile
CHANGED
@@ -1,4 +1,8 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
|
+
#
|
3
|
+
# Add a Gemfile.local to locally bundle gems outside of version control
|
4
|
+
local_gemfile = File.join(File.expand_path('..', __FILE__), 'Gemfile.local')
|
5
|
+
eval_gemfile local_gemfile if File.readable?(local_gemfile)
|
2
6
|
|
3
7
|
# Specify your gem's dependencies in active_model_serializers.gemspec
|
4
8
|
gemspec
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# ActiveModel::Serializer
|
2
2
|
|
3
|
-
[![Build Status](https://travis-ci.org/rails-api/active_model_serializers.svg)](https://travis-ci.org/rails-api/active_model_serializers)
|
3
|
+
[![Build Status](https://travis-ci.org/rails-api/active_model_serializers.svg)](https://travis-ci.org/rails-api/active_model_serializers)
|
4
4
|
<a href="https://codeclimate.com/github/rails-api/active_model_serializers"><img src="https://codeclimate.com/github/rails-api/active_model_serializers/badges/gpa.svg" /></a>
|
5
5
|
<a href="https://codeclimate.com/github/rails-api/active_model_serializers/coverage"><img src="https://codeclimate.com/github/rails-api/active_model_serializers/badges/coverage.svg" /></a>
|
6
6
|
|
@@ -138,6 +138,23 @@ render json: @post, meta: { total: 10 }, meta_key: "custom_meta"
|
|
138
138
|
|
139
139
|
`meta` will only be included in your response if you are using an Adapter that supports `root`, as JsonAPI and Json adapters, the default adapter (FlattenJson) doesn't have `root`.
|
140
140
|
|
141
|
+
### Using a serializer without `render`
|
142
|
+
|
143
|
+
At times, you might want to use a serializer without rendering it to the view. For those cases, you can create an instance of `ActiveModel::SerializableResource` with
|
144
|
+
the resource you want to be serialized and call `.serializable_hash`.
|
145
|
+
|
146
|
+
```ruby
|
147
|
+
def create
|
148
|
+
@message = current_user.messages.create!(message_params)
|
149
|
+
MessageCreationWorker.perform(serialized_message)
|
150
|
+
head 204
|
151
|
+
end
|
152
|
+
|
153
|
+
def serialized_message
|
154
|
+
ActiveModel::SerializableResource.new(@message).serializable_hash
|
155
|
+
end
|
156
|
+
```
|
157
|
+
|
141
158
|
### Overriding association methods
|
142
159
|
|
143
160
|
If you want to override any association, you can use:
|
@@ -187,12 +204,12 @@ Doesn't follow any specifc convention.
|
|
187
204
|
This adapter follows 1.0 of the format specified in
|
188
205
|
[jsonapi.org/format](http://jsonapi.org/format). It will include the associated
|
189
206
|
resources in the `"included"` member when the resource names are included in the
|
190
|
-
`include` option.
|
207
|
+
`include` option. Including nested associated resources is also supported.
|
191
208
|
|
192
209
|
```ruby
|
193
|
-
render @posts, include: ['
|
210
|
+
render @posts, include: ['author', 'comments', 'comments.author']
|
194
211
|
# or
|
195
|
-
render @posts, include: '
|
212
|
+
render @posts, include: 'author,comments,comments.author'
|
196
213
|
```
|
197
214
|
|
198
215
|
## Installation
|
@@ -283,7 +300,7 @@ The cache support is optimized to use the cached object in multiple request. An
|
|
283
300
|
|
284
301
|
**[NOTE] Every object is individually cached.**
|
285
302
|
|
286
|
-
**[NOTE] The cache is automatically expired after
|
303
|
+
**[NOTE] The cache is automatically expired after an object is updated, but it's not deleted.**
|
287
304
|
|
288
305
|
```ruby
|
289
306
|
cache(options = nil) # options: ```{key, expires_in, compress, force, race_condition_ttl}```
|
data/docs/general/adapters.md
CHANGED
@@ -30,9 +30,11 @@ resources in the `"included"` member when the resource names are included in the
|
|
30
30
|
render @posts, include: 'authors,comments'
|
31
31
|
```
|
32
32
|
|
33
|
+
The format of the `include` option can be either a String composed of a comma-separated list of [relationship paths](http://jsonapi.org/format/#fetching-includes), an Array of Symbols and Hashes, or a mix of both.
|
34
|
+
|
33
35
|
## Choosing an adapter
|
34
36
|
|
35
|
-
If you want to use a
|
37
|
+
If you want to use a specify a default adapter, such as JsonApi, you can change this in an initializer:
|
36
38
|
|
37
39
|
```ruby
|
38
40
|
ActiveModel::Serializer.config.adapter = ActiveModel::Serializer::Adapter::JsonApi
|
@@ -44,8 +46,59 @@ or
|
|
44
46
|
ActiveModel::Serializer.config.adapter = :json_api
|
45
47
|
```
|
46
48
|
|
47
|
-
If you want to have a root key in your responses you should use the Json
|
49
|
+
If you want to have a root key for each resource in your responses, you should use the Json or
|
50
|
+
JsonApi adapters instead of the default FlattenJson:
|
48
51
|
|
49
52
|
```ruby
|
50
53
|
ActiveModel::Serializer.config.adapter = :json
|
51
54
|
```
|
55
|
+
|
56
|
+
## Advanced adapter configuration
|
57
|
+
|
58
|
+
### Registering an adapter
|
59
|
+
|
60
|
+
The default adapter can be configured, as above, to use any class given to it.
|
61
|
+
|
62
|
+
An adapter may also be specified, e.g. when rendering, as a class or as a symbol.
|
63
|
+
If a symbol, then the adapter must be, e.g. `:great_example`,
|
64
|
+
`ActiveModel::Serializer::Adapter::GreatExample`, or registered.
|
65
|
+
|
66
|
+
There are two ways to register an adapter:
|
67
|
+
|
68
|
+
1) The simplest, is to subclass `ActiveModel::Serializer::Adapter`, e.g. the below will
|
69
|
+
register the `Example::UsefulAdapter` as `:useful_adapter`.
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
module Example
|
73
|
+
class UsefulAdapter < ActiveModel::Serializer::Adapter
|
74
|
+
end
|
75
|
+
end
|
76
|
+
```
|
77
|
+
|
78
|
+
You'll notice that the name it registers is the class name underscored, not the full namespace.
|
79
|
+
|
80
|
+
Under the covers, when the `ActiveModel::Serializer::Adapter` is subclassed, it registers
|
81
|
+
the subclass as `register(:useful_adapter, Example::UsefulAdapter)`
|
82
|
+
|
83
|
+
2) Any class can be registered as an adapter by calling `register` directly on the
|
84
|
+
`ActiveModel::Serializer::Adapter` class. e.g., the below registers `MyAdapter` as
|
85
|
+
`:special_adapter`.
|
86
|
+
|
87
|
+
```ruby
|
88
|
+
class MyAdapter; end
|
89
|
+
ActiveModel::Serializer::Adapter.register(:special_adapter, MyAdapter)
|
90
|
+
```
|
91
|
+
|
92
|
+
### Looking up an adapter
|
93
|
+
|
94
|
+
| `ActiveModel::Serializer::Adapter.adapter_map` | A Hash of all known adapters { adapter_name => adapter_class } |
|
95
|
+
| `ActiveModel::Serializer::Adapter.adapters` | A (sorted) Array of all known adapter_names |
|
96
|
+
| `ActiveModel::Serializer::Adapter.lookup(name_or_klass)` | The adapter_class, else raises an `ActiveModel::Serializer::Adapter::UnknownAdapter` error |
|
97
|
+
| `ActiveModel::Serializer::Adapter.adapter_class(adapter)` | delegates to `ActiveModel::Serializer::Adapter.lookup(adapter)` |
|
98
|
+
| `ActiveModel::Serializer.adapter` | a convenience method for `ActiveModel::Serializer::Adapter.lookup(config.adapter)` |
|
99
|
+
|
100
|
+
The registered adapter name is always a String, but may be looked up as a Symbol or String.
|
101
|
+
Helpfully, the Symbol or String is underscored, so that `get(:my_adapter)` and `get("MyAdapter")`
|
102
|
+
may both be used.
|
103
|
+
|
104
|
+
For more information, see [the Adapter class on GitHub](https://github.com/rails-api/active_model_serializers/blob/master/lib/active_model/serializer/adapter.rb)
|
@@ -6,6 +6,9 @@ module ActionController
|
|
6
6
|
|
7
7
|
include ActionController::Renderers
|
8
8
|
|
9
|
+
# Deprecated
|
10
|
+
ADAPTER_OPTION_KEYS = ActiveModel::SerializableResource::ADAPTER_OPTION_KEYS
|
11
|
+
|
9
12
|
included do
|
10
13
|
class_attribute :_serialization_scope
|
11
14
|
self._serialization_scope = :current_user
|
@@ -10,6 +10,7 @@ module ActiveModel
|
|
10
10
|
autoload :Lint
|
11
11
|
autoload :Associations
|
12
12
|
autoload :Fieldset
|
13
|
+
autoload :Utils
|
13
14
|
include Configuration
|
14
15
|
include Associations
|
15
16
|
|
@@ -94,19 +95,9 @@ module ActiveModel
|
|
94
95
|
end
|
95
96
|
end
|
96
97
|
|
98
|
+
# @see ActiveModel::Serializer::Adapter.lookup
|
97
99
|
def self.adapter
|
98
|
-
|
99
|
-
when Symbol
|
100
|
-
ActiveModel::Serializer::Adapter.adapter_class(config.adapter)
|
101
|
-
when Class
|
102
|
-
config.adapter
|
103
|
-
end
|
104
|
-
unless adapter_class
|
105
|
-
valid_adapters = Adapter.constants.map { |klass| ":#{klass.to_s.downcase}" }
|
106
|
-
raise ArgumentError, "Unknown adapter: #{config.adapter}. Valid adapters are: #{valid_adapters}"
|
107
|
-
end
|
108
|
-
|
109
|
-
adapter_class
|
100
|
+
ActiveModel::Serializer::Adapter.lookup(config.adapter)
|
110
101
|
end
|
111
102
|
|
112
103
|
def self.root_name
|
@@ -1,12 +1,15 @@
|
|
1
1
|
module ActiveModel
|
2
2
|
class Serializer
|
3
3
|
class Adapter
|
4
|
+
UnknownAdapterError = Class.new(ArgumentError)
|
5
|
+
ADAPTER_MAP = {}
|
6
|
+
private_constant :ADAPTER_MAP if defined?(private_constant)
|
4
7
|
extend ActiveSupport::Autoload
|
5
|
-
require 'active_model/serializer/adapter/json'
|
6
|
-
require 'active_model/serializer/adapter/json_api'
|
7
|
-
autoload :FlattenJson
|
8
|
-
autoload :Null
|
9
8
|
autoload :FragmentCache
|
9
|
+
autoload :Json
|
10
|
+
autoload :JsonApi
|
11
|
+
autoload :Null
|
12
|
+
autoload :FlattenJson
|
10
13
|
|
11
14
|
def self.create(resource, options = {})
|
12
15
|
override = options.delete(:adapter)
|
@@ -14,9 +17,67 @@ module ActiveModel
|
|
14
17
|
klass.new(resource, options)
|
15
18
|
end
|
16
19
|
|
20
|
+
# @see ActiveModel::Serializer::Adapter.lookup
|
17
21
|
def self.adapter_class(adapter)
|
18
|
-
|
19
|
-
|
22
|
+
ActiveModel::Serializer::Adapter.lookup(adapter)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Only the Adapter class has these methods.
|
26
|
+
# None of the sublasses have them.
|
27
|
+
class << ActiveModel::Serializer::Adapter
|
28
|
+
# @return Hash<adapter_name, adapter_class>
|
29
|
+
def adapter_map
|
30
|
+
ADAPTER_MAP
|
31
|
+
end
|
32
|
+
|
33
|
+
# @return [Array<Symbol>] list of adapter names
|
34
|
+
def adapters
|
35
|
+
adapter_map.keys.sort
|
36
|
+
end
|
37
|
+
|
38
|
+
# Adds an adapter 'klass' with 'name' to the 'adapter_map'
|
39
|
+
# Names are stringified and underscored
|
40
|
+
# @param [Symbol, String] name of the registered adapter
|
41
|
+
# @param [Class] klass - adapter class itself
|
42
|
+
# @example
|
43
|
+
# AMS::Adapter.register(:my_adapter, MyAdapter)
|
44
|
+
def register(name, klass)
|
45
|
+
adapter_map.update(name.to_s.underscore => klass)
|
46
|
+
self
|
47
|
+
end
|
48
|
+
|
49
|
+
# @param adapter [String, Symbol, Class] name to fetch adapter by
|
50
|
+
# @return [ActiveModel::Serializer::Adapter] subclass of Adapter
|
51
|
+
# @raise [UnknownAdapterError]
|
52
|
+
def lookup(adapter)
|
53
|
+
# 1. return if is a class
|
54
|
+
return adapter if adapter.is_a?(Class)
|
55
|
+
adapter_name = adapter.to_s.underscore
|
56
|
+
# 2. return if registered
|
57
|
+
adapter_map.fetch(adapter_name) {
|
58
|
+
# 3. try to find adapter class from environment
|
59
|
+
adapter_class = find_by_name(adapter_name)
|
60
|
+
register(adapter_name, adapter_class)
|
61
|
+
adapter_class
|
62
|
+
}
|
63
|
+
rescue NameError, ArgumentError => e
|
64
|
+
failure_message =
|
65
|
+
"NameError: #{e.message}. Unknown adapter: #{adapter.inspect}. Valid adapters are: #{adapters}"
|
66
|
+
raise UnknownAdapterError, failure_message, e.backtrace
|
67
|
+
end
|
68
|
+
|
69
|
+
# @api private
|
70
|
+
def find_by_name(adapter_name)
|
71
|
+
adapter_name = adapter_name.to_s.classify.tr('API', 'Api')
|
72
|
+
ActiveModel::Serializer::Adapter.const_get(adapter_name.to_sym) or # rubocop:disable Style/AndOr
|
73
|
+
fail UnknownAdapterError
|
74
|
+
end
|
75
|
+
private :find_by_name
|
76
|
+
end
|
77
|
+
|
78
|
+
# Automatically register adapters when subclassing
|
79
|
+
def self.inherited(subclass)
|
80
|
+
ActiveModel::Serializer::Adapter.register(subclass.to_s.demodulize, subclass)
|
20
81
|
end
|
21
82
|
|
22
83
|
attr_reader :serializer
|
@@ -1,10 +1,6 @@
|
|
1
|
-
|
2
|
-
class Serializer
|
3
|
-
class Adapter
|
4
|
-
class FlattenJson < Json
|
1
|
+
class ActiveModel::Serializer::Adapter::FlattenJson < ActiveModel::Serializer::Adapter::Json
|
5
2
|
def serializable_hash(options = {})
|
6
|
-
super
|
7
|
-
@result
|
3
|
+
super.each_value.first
|
8
4
|
end
|
9
5
|
|
10
6
|
private
|
@@ -13,7 +9,4 @@ module ActiveModel
|
|
13
9
|
def include_meta(json)
|
14
10
|
json
|
15
11
|
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
12
|
end
|
@@ -1,7 +1,4 @@
|
|
1
|
-
|
2
|
-
class Serializer
|
3
|
-
class Adapter
|
4
|
-
class FragmentCache
|
1
|
+
class ActiveModel::Serializer::Adapter::FragmentCache
|
5
2
|
attr_reader :serializer
|
6
3
|
|
7
4
|
def initialize(adapter, serializer, options)
|
@@ -75,7 +72,4 @@ module ActiveModel
|
|
75
72
|
def to_valid_const_name(name)
|
76
73
|
name.gsub('::', '_')
|
77
74
|
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
75
|
end
|
@@ -1,17 +1,15 @@
|
|
1
|
-
|
1
|
+
class ActiveModel::Serializer::Adapter::Json < ActiveModel::Serializer::Adapter
|
2
|
+
extend ActiveSupport::Autoload
|
3
|
+
autoload :FragmentCache
|
2
4
|
|
3
|
-
module ActiveModel
|
4
|
-
class Serializer
|
5
|
-
class Adapter
|
6
|
-
class Json < Adapter
|
7
5
|
def serializable_hash(options = nil)
|
8
6
|
options ||= {}
|
9
7
|
if serializer.respond_to?(:each)
|
10
|
-
|
8
|
+
result = serializer.map { |s| FlattenJson.new(s).serializable_hash(options) }
|
11
9
|
else
|
12
|
-
|
10
|
+
hash = {}
|
13
11
|
|
14
|
-
|
12
|
+
core = cache_check(serializer) do
|
15
13
|
serializer.attributes(options)
|
16
14
|
end
|
17
15
|
|
@@ -21,13 +19,13 @@ module ActiveModel
|
|
21
19
|
|
22
20
|
if serializer.respond_to?(:each)
|
23
21
|
array_serializer = serializer
|
24
|
-
|
22
|
+
hash[association.key] = array_serializer.map do |item|
|
25
23
|
cache_check(item) do
|
26
24
|
item.attributes(opts)
|
27
25
|
end
|
28
26
|
end
|
29
27
|
else
|
30
|
-
|
28
|
+
hash[association.key] =
|
31
29
|
if serializer && serializer.object
|
32
30
|
cache_check(serializer) do
|
33
31
|
serializer.attributes(options)
|
@@ -37,16 +35,13 @@ module ActiveModel
|
|
37
35
|
end
|
38
36
|
end
|
39
37
|
end
|
40
|
-
|
38
|
+
result = core.merge hash
|
41
39
|
end
|
42
40
|
|
43
|
-
{ root =>
|
41
|
+
{ root => result }
|
44
42
|
end
|
45
43
|
|
46
44
|
def fragment_cache(cached_hash, non_cached_hash)
|
47
|
-
Json::FragmentCache.new().fragment_cache(cached_hash, non_cached_hash)
|
45
|
+
ActiveModel::Serializer::Adapter::Json::FragmentCache.new().fragment_cache(cached_hash, non_cached_hash)
|
48
46
|
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
47
|
end
|
@@ -1,14 +1,5 @@
|
|
1
|
-
|
2
|
-
module ActiveModel
|
3
|
-
class Serializer
|
4
|
-
class Adapter
|
5
|
-
class Json < Adapter
|
6
|
-
class FragmentCache
|
1
|
+
class ActiveModel::Serializer::Adapter::Json::FragmentCache
|
7
2
|
def fragment_cache(cached_hash, non_cached_hash)
|
8
3
|
non_cached_hash.merge cached_hash
|
9
4
|
end
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
5
|
end
|
@@ -1,19 +1,13 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
class ActiveModel::Serializer::Adapter::JsonApi < ActiveModel::Serializer::Adapter
|
2
|
+
extend ActiveSupport::Autoload
|
3
|
+
autoload :PaginationLinks
|
4
|
+
autoload :FragmentCache
|
3
5
|
|
4
|
-
module ActiveModel
|
5
|
-
class Serializer
|
6
|
-
class Adapter
|
7
|
-
class JsonApi < Adapter
|
8
6
|
def initialize(serializer, options = {})
|
9
7
|
super
|
10
8
|
@hash = { data: [] }
|
11
9
|
|
12
|
-
@options[:include]
|
13
|
-
if @options[:include].is_a?(String)
|
14
|
-
@options[:include] = @options[:include].split(',')
|
15
|
-
end
|
16
|
-
|
10
|
+
@included = ActiveModel::Serializer::Utils.include_args_to_hash(@options[:include])
|
17
11
|
fields = options.delete(:fields)
|
18
12
|
if fields
|
19
13
|
@fieldset = ActiveModel::Serializer::Fieldset.new(fields, serializer.json_key)
|
@@ -49,7 +43,7 @@ module ActiveModel
|
|
49
43
|
|
50
44
|
def fragment_cache(cached_hash, non_cached_hash)
|
51
45
|
root = false if @options.include?(:include)
|
52
|
-
JsonApi::FragmentCache.new.fragment_cache(root, cached_hash, non_cached_hash)
|
46
|
+
ActiveModel::Serializer::Adapter::JsonApi::FragmentCache.new().fragment_cache(root, cached_hash, non_cached_hash)
|
53
47
|
end
|
54
48
|
|
55
49
|
private
|
@@ -62,6 +56,12 @@ module ActiveModel
|
|
62
56
|
end
|
63
57
|
end
|
64
58
|
|
59
|
+
def add_relationships(resource, name, serializers)
|
60
|
+
resource[:relationships] ||= {}
|
61
|
+
resource[:relationships][name] ||= { data: [] }
|
62
|
+
resource[:relationships][name][:data] += serializers.map { |serializer| { type: serializer.json_api_type, id: serializer.id.to_s } }
|
63
|
+
end
|
64
|
+
|
65
65
|
def resource_identifier_id_for(serializer)
|
66
66
|
if serializer.respond_to?(:id)
|
67
67
|
serializer.id
|
@@ -113,56 +113,46 @@ module ActiveModel
|
|
113
113
|
end
|
114
114
|
|
115
115
|
def included_for(serializer)
|
116
|
-
|
116
|
+
included = @included.flat_map do |inc|
|
117
|
+
association = serializer.associations.find { |assoc| assoc.key == inc.first }
|
118
|
+
_included_for(association.serializer, inc.second) if association
|
119
|
+
end
|
120
|
+
|
121
|
+
included.uniq
|
117
122
|
end
|
118
123
|
|
119
|
-
def _included_for(
|
124
|
+
def _included_for(serializer, includes)
|
120
125
|
if serializer.respond_to?(:each)
|
121
|
-
serializer.flat_map { |s| _included_for(
|
126
|
+
serializer.flat_map { |s| _included_for(s, includes) }.uniq
|
122
127
|
else
|
123
128
|
return [] unless serializer && serializer.object
|
124
|
-
result = []
|
125
|
-
resource_path = [parent, resource_name].compact.join('.')
|
126
|
-
|
127
|
-
if include_assoc?(resource_path)
|
128
|
-
primary_data = primary_data_for(serializer, @options)
|
129
|
-
relationships = relationships_for(serializer)
|
130
|
-
primary_data[:relationships] = relationships if relationships.any?
|
131
|
-
result.push(primary_data)
|
132
|
-
end
|
133
129
|
|
134
|
-
|
135
|
-
|
130
|
+
primary_data = primary_data_for(serializer, @options)
|
131
|
+
relationships = relationships_for(serializer)
|
132
|
+
primary_data[:relationships] = relationships if relationships.any?
|
133
|
+
|
134
|
+
included = [primary_data]
|
136
135
|
|
137
|
-
|
138
|
-
|
139
|
-
|
136
|
+
includes.each do |inc|
|
137
|
+
association = serializer.associations.find { |assoc| assoc.key == inc.first }
|
138
|
+
if association
|
139
|
+
included.concat(_included_for(association.serializer, inc.second))
|
140
|
+
included.uniq!
|
140
141
|
end
|
141
142
|
end
|
142
|
-
result
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
def include_assoc?(assoc)
|
147
|
-
check_assoc("#{assoc}$")
|
148
|
-
end
|
149
|
-
|
150
|
-
def include_nested_assoc?(assoc)
|
151
|
-
check_assoc("#{assoc}.")
|
152
|
-
end
|
153
143
|
|
154
|
-
|
155
|
-
|
144
|
+
included
|
145
|
+
end
|
156
146
|
end
|
157
147
|
|
158
148
|
def add_links(options)
|
159
|
-
links = @hash.fetch(:
|
149
|
+
links = @hash.fetch(:links) { {} }
|
160
150
|
collection = serializer.object
|
161
|
-
@hash[:
|
151
|
+
@hash[:links] = add_pagination_links(links, collection, options) if paginated?(collection)
|
162
152
|
end
|
163
153
|
|
164
|
-
def add_pagination_links(links,
|
165
|
-
pagination_links = JsonApi::PaginationLinks.new(
|
154
|
+
def add_pagination_links(links, resources, options)
|
155
|
+
pagination_links = ActiveModel::Serializer::Adapter::JsonApi::PaginationLinks.new(resources, options[:context]).serializable_hash(options)
|
166
156
|
links.update(pagination_links)
|
167
157
|
end
|
168
158
|
|
@@ -171,7 +161,4 @@ module ActiveModel
|
|
171
161
|
collection.respond_to?(:total_pages) &&
|
172
162
|
collection.respond_to?(:size)
|
173
163
|
end
|
174
|
-
end
|
175
|
-
end
|
176
|
-
end
|
177
164
|
end
|
@@ -1,9 +1,4 @@
|
|
1
|
-
|
2
|
-
module ActiveModel
|
3
|
-
class Serializer
|
4
|
-
class Adapter
|
5
|
-
class JsonApi < Adapter
|
6
|
-
class FragmentCache
|
1
|
+
class ActiveModel::Serializer::Adapter::JsonApi::FragmentCache
|
7
2
|
def fragment_cache(root, cached_hash, non_cached_hash)
|
8
3
|
hash = {}
|
9
4
|
core_cached = cached_hash.first
|
@@ -15,8 +10,4 @@ module ActiveModel
|
|
15
10
|
|
16
11
|
hash.deep_merge no_root_non_cache.deep_merge no_root_cache
|
17
12
|
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
13
|
end
|
@@ -1,8 +1,4 @@
|
|
1
|
-
|
2
|
-
class Serializer
|
3
|
-
class Adapter
|
4
|
-
class JsonApi < Adapter
|
5
|
-
class PaginationLinks
|
1
|
+
class ActiveModel::Serializer::Adapter::JsonApi::PaginationLinks
|
6
2
|
FIRST_PAGE = 1
|
7
3
|
|
8
4
|
attr_reader :collection, :context
|
@@ -51,8 +47,4 @@ module ActiveModel
|
|
51
47
|
def query_parameters
|
52
48
|
@query_parameters ||= context.query_parameters
|
53
49
|
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
50
|
end
|
@@ -18,7 +18,7 @@ module ActiveModel
|
|
18
18
|
private
|
19
19
|
|
20
20
|
ActiveModelSerializers.silence_warnings do
|
21
|
-
|
21
|
+
attr_reader :raw_fields, :root
|
22
22
|
end
|
23
23
|
|
24
24
|
def parsed_fields
|
@@ -26,7 +26,7 @@ module ActiveModel
|
|
26
26
|
raw_fields.inject({}) { |h, (k, v)| h[k.to_sym] = v.map(&:to_sym); h }
|
27
27
|
elsif raw_fields.is_a?(Array)
|
28
28
|
if root.nil?
|
29
|
-
raise ArgumentError, 'The root argument must be specified if the
|
29
|
+
raise ArgumentError, 'The root argument must be specified if the fields argument is an array.'
|
30
30
|
end
|
31
31
|
hash = {}
|
32
32
|
hash[root.to_sym] = raw_fields.map(&:to_sym)
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module ActiveModel::Serializer::Utils
|
2
|
+
module_function
|
3
|
+
|
4
|
+
# Translates a comma separated list of dot separated paths (JSONAPI format) into a Hash.
|
5
|
+
# Example: `'posts.author, posts.comments.upvotes, posts.comments.author'` would become `{ posts: { author: {}, comments: { author: {}, upvotes: {} } } }`.
|
6
|
+
#
|
7
|
+
# @param [String] included
|
8
|
+
# @return [Hash] a Hash representing the same tree structure
|
9
|
+
def include_string_to_hash(included)
|
10
|
+
included.delete(' ').split(',').inject({}) do |hash, path|
|
11
|
+
hash.deep_merge!(path.split('.').reverse_each.inject({}) { |a, e| { e.to_sym => a } })
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Translates the arguments passed to the include option into a Hash. The format can be either
|
16
|
+
# a String (see #include_string_to_hash), an Array of Symbols and Hashes, or a mix of both.
|
17
|
+
# Example: `posts: [:author, comments: [:author, :upvotes]]` would become `{ posts: { author: {}, comments: { author: {}, upvotes: {} } } }`.
|
18
|
+
#
|
19
|
+
# @param [Symbol, Hash, Array, String] included
|
20
|
+
# @return [Hash] a Hash representing the same tree structure
|
21
|
+
def include_args_to_hash(included)
|
22
|
+
case included
|
23
|
+
when Symbol
|
24
|
+
{ included => {} }
|
25
|
+
when Hash
|
26
|
+
included.each_with_object({}) { |(key, value), hash| hash[key] = include_args_to_hash(value) }
|
27
|
+
when Array
|
28
|
+
included.inject({}) { |a, e| a.merge!(include_args_to_hash(e)) }
|
29
|
+
when String
|
30
|
+
include_string_to_hash(included)
|
31
|
+
else
|
32
|
+
{}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -43,29 +43,29 @@ module ActionController
|
|
43
43
|
|
44
44
|
def render_resource_with_include
|
45
45
|
setup_post
|
46
|
-
render json: @post, include:
|
46
|
+
render json: @post, include: [:author], adapter: :json_api
|
47
47
|
end
|
48
48
|
|
49
49
|
def render_resource_with_nested_include
|
50
50
|
setup_post
|
51
|
-
render json: @post, include:
|
51
|
+
render json: @post, include: [comments: [:author]], adapter: :json_api
|
52
52
|
end
|
53
53
|
|
54
54
|
def render_resource_with_nested_has_many_include
|
55
55
|
setup_post
|
56
|
-
render json: @post, include:
|
56
|
+
render json: @post, include: 'author.roles', adapter: :json_api
|
57
57
|
end
|
58
58
|
|
59
59
|
def render_resource_with_missing_nested_has_many_include
|
60
60
|
setup_post
|
61
61
|
@post.author = @author2 # author2 has no roles.
|
62
|
-
render json: @post, include:
|
62
|
+
render json: @post, include: [author: [:roles]], adapter: :json_api
|
63
63
|
end
|
64
64
|
|
65
65
|
def render_collection_with_missing_nested_has_many_include
|
66
66
|
setup_post
|
67
67
|
@post.author = @author2
|
68
|
-
render json: [@post, @post2], include:
|
68
|
+
render json: [@post, @post2], include: [author: [:roles]], adapter: :json_api
|
69
69
|
end
|
70
70
|
|
71
71
|
def render_collection_without_include
|
@@ -75,7 +75,7 @@ module ActionController
|
|
75
75
|
|
76
76
|
def render_collection_with_include
|
77
77
|
setup_post
|
78
|
-
render json: [@post], include:
|
78
|
+
render json: [@post], include: 'author, comments', adapter: :json_api
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
@@ -141,8 +141,7 @@ module ActionController
|
|
141
141
|
get :render_resource_with_nested_include
|
142
142
|
response = JSON.parse(@response.body)
|
143
143
|
assert response.key? 'included'
|
144
|
-
assert_equal
|
145
|
-
assert_equal 'Anonymous', response['included'].first['attributes']['name']
|
144
|
+
assert_equal 3, response['included'].size
|
146
145
|
end
|
147
146
|
|
148
147
|
def test_render_collection_without_include
|
@@ -38,7 +38,7 @@ module ActiveModel
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def test_includes_linked_post
|
41
|
-
@adapter = ActiveModel::Serializer::Adapter::JsonApi.new(@serializer, include:
|
41
|
+
@adapter = ActiveModel::Serializer::Adapter::JsonApi.new(@serializer, include: [:post])
|
42
42
|
expected = [{
|
43
43
|
id: '42',
|
44
44
|
type: 'posts',
|
@@ -56,7 +56,7 @@ module ActiveModel
|
|
56
56
|
end
|
57
57
|
|
58
58
|
def test_limiting_linked_post_fields
|
59
|
-
@adapter = ActiveModel::Serializer::Adapter::JsonApi.new(@serializer, include:
|
59
|
+
@adapter = ActiveModel::Serializer::Adapter::JsonApi.new(@serializer, include: [:post], fields: { post: [:title] })
|
60
60
|
expected = [{
|
61
61
|
id: '42',
|
62
62
|
type: 'posts',
|
@@ -108,7 +108,7 @@ module ActiveModel
|
|
108
108
|
|
109
109
|
def test_include_linked_resources_with_type_name
|
110
110
|
serializer = BlogSerializer.new(@blog)
|
111
|
-
adapter = ActiveModel::Serializer::Adapter::JsonApi.new(serializer, include:
|
111
|
+
adapter = ActiveModel::Serializer::Adapter::JsonApi.new(serializer, include: [:writer, :articles])
|
112
112
|
linked = adapter.serializable_hash[:included]
|
113
113
|
expected = [
|
114
114
|
{
|
@@ -42,7 +42,7 @@ module ActiveModel
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def test_includes_linked_comments
|
45
|
-
@adapter = ActiveModel::Serializer::Adapter::JsonApi.new(@serializer, include:
|
45
|
+
@adapter = ActiveModel::Serializer::Adapter::JsonApi.new(@serializer, include: [:comments])
|
46
46
|
expected = [{
|
47
47
|
id: '1',
|
48
48
|
type: 'comments',
|
@@ -68,7 +68,7 @@ module ActiveModel
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def test_limit_fields_of_linked_comments
|
71
|
-
@adapter = ActiveModel::Serializer::Adapter::JsonApi.new(@serializer, include:
|
71
|
+
@adapter = ActiveModel::Serializer::Adapter::JsonApi.new(@serializer, include: [:comments], fields: { comment: [:id] })
|
72
72
|
expected = [{
|
73
73
|
id: '1',
|
74
74
|
type: 'comments',
|
@@ -28,7 +28,7 @@ module ActiveModel
|
|
28
28
|
@virtual_value = VirtualValue.new(id: 1)
|
29
29
|
|
30
30
|
@serializer = AuthorSerializer.new(@author)
|
31
|
-
@adapter = ActiveModel::Serializer::Adapter::JsonApi.new(@serializer, include:
|
31
|
+
@adapter = ActiveModel::Serializer::Adapter::JsonApi.new(@serializer, include: [:bio, :posts])
|
32
32
|
end
|
33
33
|
|
34
34
|
def test_includes_bio_id
|
@@ -38,7 +38,7 @@ module ActiveModel
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def test_includes_linked_bio
|
41
|
-
@adapter = ActiveModel::Serializer::Adapter::JsonApi.new(@serializer, include:
|
41
|
+
@adapter = ActiveModel::Serializer::Adapter::JsonApi.new(@serializer, include: [:bio])
|
42
42
|
|
43
43
|
expected = [
|
44
44
|
{
|
@@ -43,11 +43,11 @@ module ActiveModel
|
|
43
43
|
serializer = ArraySerializer.new([@first_post, @second_post])
|
44
44
|
adapter = ActiveModel::Serializer::Adapter::JsonApi.new(
|
45
45
|
serializer,
|
46
|
-
include: [
|
46
|
+
include: [:comments, author: [:bio]]
|
47
47
|
)
|
48
48
|
alt_adapter = ActiveModel::Serializer::Adapter::JsonApi.new(
|
49
49
|
serializer,
|
50
|
-
include:
|
50
|
+
include: [:comments, author: [:bio]]
|
51
51
|
)
|
52
52
|
|
53
53
|
expected = {
|
@@ -153,11 +153,11 @@ module ActiveModel
|
|
153
153
|
serializer = BioSerializer.new @bio1
|
154
154
|
adapter = ActiveModel::Serializer::Adapter::JsonApi.new(
|
155
155
|
serializer,
|
156
|
-
include: [
|
156
|
+
include: [author: [:posts]]
|
157
157
|
)
|
158
158
|
alt_adapter = ActiveModel::Serializer::Adapter::JsonApi.new(
|
159
159
|
serializer,
|
160
|
-
include:
|
160
|
+
include: [author: [:posts]]
|
161
161
|
)
|
162
162
|
|
163
163
|
expected = [
|
@@ -224,7 +224,7 @@ module ActiveModel
|
|
224
224
|
serializer = ArraySerializer.new([@first_comment, @second_comment])
|
225
225
|
adapter = ActiveModel::Serializer::Adapter::JsonApi.new(
|
226
226
|
serializer,
|
227
|
-
include: [
|
227
|
+
include: [:post]
|
228
228
|
)
|
229
229
|
|
230
230
|
expected = [
|
@@ -257,7 +257,7 @@ module ActiveModel
|
|
257
257
|
serializer = PostPreviewSerializer.new(@first_post)
|
258
258
|
adapter = ActiveModel::Serializer::Adapter::JsonApi.new(
|
259
259
|
serializer,
|
260
|
-
include: [
|
260
|
+
include: [:author]
|
261
261
|
)
|
262
262
|
|
263
263
|
expected = {
|
data/test/adapter_test.rb
CHANGED
@@ -19,16 +19,6 @@ module ActiveModel
|
|
19
19
|
assert_equal @serializer, @adapter.serializer
|
20
20
|
end
|
21
21
|
|
22
|
-
def test_adapter_class_for_known_adapter
|
23
|
-
klass = ActiveModel::Serializer::Adapter.adapter_class(:json_api)
|
24
|
-
assert_equal ActiveModel::Serializer::Adapter::JsonApi, klass
|
25
|
-
end
|
26
|
-
|
27
|
-
def test_adapter_class_for_unknown_adapter
|
28
|
-
klass = ActiveModel::Serializer::Adapter.adapter_class(:json_simple)
|
29
|
-
assert_nil klass
|
30
|
-
end
|
31
|
-
|
32
22
|
def test_create_adapter
|
33
23
|
adapter = ActiveModel::Serializer::Adapter.create(@serializer)
|
34
24
|
assert_equal ActiveModel::Serializer::Adapter::FlattenJson, adapter.class
|
@@ -1,8 +1,15 @@
|
|
1
1
|
module ActiveModel
|
2
2
|
class Serializer
|
3
3
|
class AdapterForTest < Minitest::Test
|
4
|
+
UnknownAdapterError = ::ActiveModel::Serializer::Adapter::UnknownAdapterError
|
5
|
+
|
4
6
|
def setup
|
5
7
|
@previous_adapter = ActiveModel::Serializer.config.adapter
|
8
|
+
# Eager load adapters
|
9
|
+
ActiveModel::Serializer::Adapter.eager_load!
|
10
|
+
[:json_api, :flatten_json, :null, :json].each do |adapter_name|
|
11
|
+
ActiveModel::Serializer::Adapter.lookup(adapter_name)
|
12
|
+
end
|
6
13
|
end
|
7
14
|
|
8
15
|
def teardown
|
@@ -20,6 +27,7 @@ module ActiveModel
|
|
20
27
|
adapter = ActiveModel::Serializer.adapter
|
21
28
|
assert_equal ActiveModel::Serializer::Adapter::Null, adapter
|
22
29
|
ensure
|
30
|
+
ActiveModel::Serializer.config.adapter = @previous_adapter
|
23
31
|
end
|
24
32
|
|
25
33
|
def test_overwrite_adapter_with_class
|
@@ -32,7 +40,7 @@ module ActiveModel
|
|
32
40
|
def test_raises_exception_if_invalid_symbol_given
|
33
41
|
ActiveModel::Serializer.config.adapter = :unknown
|
34
42
|
|
35
|
-
assert_raises
|
43
|
+
assert_raises UnknownAdapterError do
|
36
44
|
ActiveModel::Serializer.adapter
|
37
45
|
end
|
38
46
|
end
|
@@ -40,10 +48,123 @@ module ActiveModel
|
|
40
48
|
def test_raises_exception_if_it_does_not_know_hot_to_infer_adapter
|
41
49
|
ActiveModel::Serializer.config.adapter = 42
|
42
50
|
|
43
|
-
assert_raises
|
51
|
+
assert_raises UnknownAdapterError do
|
44
52
|
ActiveModel::Serializer.adapter
|
45
53
|
end
|
46
54
|
end
|
55
|
+
|
56
|
+
def test_adapter_class_for_known_adapter
|
57
|
+
klass = ActiveModel::Serializer::Adapter.adapter_class(:json_api)
|
58
|
+
assert_equal ActiveModel::Serializer::Adapter::JsonApi, klass
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_adapter_class_for_unknown_adapter
|
62
|
+
assert_raises UnknownAdapterError do
|
63
|
+
ActiveModel::Serializer::Adapter.adapter_class(:json_simple)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_adapter_map
|
68
|
+
expected_adapter_map = {
|
69
|
+
'json'.freeze => ActiveModel::Serializer::Adapter::Json,
|
70
|
+
'json_api'.freeze => ActiveModel::Serializer::Adapter::JsonApi,
|
71
|
+
'flatten_json'.freeze => ActiveModel::Serializer::Adapter::FlattenJson,
|
72
|
+
'null'.freeze => ActiveModel::Serializer::Adapter::Null
|
73
|
+
}
|
74
|
+
assert_equal ActiveModel::Serializer::Adapter.adapter_map, expected_adapter_map
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_adapters
|
78
|
+
assert_equal ActiveModel::Serializer::Adapter.adapters.sort, [
|
79
|
+
'flatten_json'.freeze,
|
80
|
+
'json'.freeze,
|
81
|
+
'json_api'.freeze,
|
82
|
+
'null'.freeze
|
83
|
+
]
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_lookup_adapter_by_string_name
|
87
|
+
assert_equal ActiveModel::Serializer::Adapter.lookup('json'.freeze), ActiveModel::Serializer::Adapter::Json
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_lookup_adapter_by_symbol_name
|
91
|
+
assert_equal ActiveModel::Serializer::Adapter.lookup(:json), ActiveModel::Serializer::Adapter::Json
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_lookup_adapter_by_class
|
95
|
+
klass = ActiveModel::Serializer::Adapter::Json
|
96
|
+
assert_equal ActiveModel::Serializer::Adapter.lookup(klass), klass
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_lookup_adapter_from_environment_registers_adapter
|
100
|
+
ActiveModel::Serializer::Adapter.const_set(:AdapterFromEnvironment, Class.new)
|
101
|
+
klass = ::ActiveModel::Serializer::Adapter::AdapterFromEnvironment
|
102
|
+
name = 'adapter_from_environment'.freeze
|
103
|
+
assert_equal ActiveModel::Serializer::Adapter.lookup(name), klass
|
104
|
+
assert ActiveModel::Serializer::Adapter.adapters.include?(name)
|
105
|
+
ensure
|
106
|
+
ActiveModel::Serializer::Adapter.adapter_map.delete(name)
|
107
|
+
ActiveModel::Serializer::Adapter.send(:remove_const, :AdapterFromEnvironment)
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_lookup_adapter_for_unknown_name
|
111
|
+
assert_raises UnknownAdapterError do
|
112
|
+
ActiveModel::Serializer::Adapter.lookup(:json_simple)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_adapter
|
117
|
+
assert_equal ActiveModel::Serializer.config.adapter, :flatten_json
|
118
|
+
assert_equal ActiveModel::Serializer.adapter, ActiveModel::Serializer::Adapter::FlattenJson
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_register_adapter
|
122
|
+
new_adapter_name = :foo
|
123
|
+
new_adapter_klass = Class.new
|
124
|
+
ActiveModel::Serializer::Adapter.register(new_adapter_name, new_adapter_klass)
|
125
|
+
assert ActiveModel::Serializer::Adapter.adapters.include?('foo'.freeze)
|
126
|
+
assert ActiveModel::Serializer::Adapter.lookup(:foo), new_adapter_klass
|
127
|
+
ensure
|
128
|
+
ActiveModel::Serializer::Adapter.adapter_map.delete(new_adapter_name.to_s)
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_inherited_adapter_hooks_register_adapter
|
132
|
+
Object.const_set(:MyAdapter, Class.new)
|
133
|
+
my_adapter = MyAdapter
|
134
|
+
ActiveModel::Serializer::Adapter.inherited(my_adapter)
|
135
|
+
assert_equal ActiveModel::Serializer::Adapter.lookup(:my_adapter), my_adapter
|
136
|
+
ensure
|
137
|
+
ActiveModel::Serializer::Adapter.adapter_map.delete('my_adapter'.freeze)
|
138
|
+
Object.send(:remove_const, :MyAdapter)
|
139
|
+
end
|
140
|
+
|
141
|
+
def test_inherited_adapter_hooks_register_demodulized_adapter
|
142
|
+
Object.const_set(:MyNamespace, Module.new)
|
143
|
+
MyNamespace.const_set(:MyAdapter, Class.new)
|
144
|
+
my_adapter = MyNamespace::MyAdapter
|
145
|
+
ActiveModel::Serializer::Adapter.inherited(my_adapter)
|
146
|
+
assert_equal ActiveModel::Serializer::Adapter.lookup(:my_adapter), my_adapter
|
147
|
+
ensure
|
148
|
+
ActiveModel::Serializer::Adapter.adapter_map.delete('my_adapter'.freeze)
|
149
|
+
MyNamespace.send(:remove_const, :MyAdapter)
|
150
|
+
Object.send(:remove_const, :MyNamespace)
|
151
|
+
end
|
152
|
+
|
153
|
+
def test_inherited_adapter_hooks_register_subclass_of_registered_adapter
|
154
|
+
Object.const_set(:MyAdapter, Class.new)
|
155
|
+
my_adapter = MyAdapter
|
156
|
+
Object.const_set(:MySubclassedAdapter, Class.new(MyAdapter))
|
157
|
+
my_subclassed_adapter = MySubclassedAdapter
|
158
|
+
ActiveModel::Serializer::Adapter.inherited(my_adapter)
|
159
|
+
ActiveModel::Serializer::Adapter.inherited(my_subclassed_adapter)
|
160
|
+
assert_equal ActiveModel::Serializer::Adapter.lookup(:my_adapter), my_adapter
|
161
|
+
assert_equal ActiveModel::Serializer::Adapter.lookup(:my_subclassed_adapter), my_subclassed_adapter
|
162
|
+
ensure
|
163
|
+
ActiveModel::Serializer::Adapter.adapter_map.delete('my_adapter'.freeze)
|
164
|
+
ActiveModel::Serializer::Adapter.adapter_map.delete('my_subclassed_adapter'.freeze)
|
165
|
+
Object.send(:remove_const, :MyAdapter)
|
166
|
+
Object.send(:remove_const, :MySubclassedAdapter)
|
167
|
+
end
|
47
168
|
end
|
48
169
|
end
|
49
170
|
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module ActiveModel
|
4
|
+
class Serializer
|
5
|
+
module Utils
|
6
|
+
class IncludeArgsToHashTest < Minitest::Test
|
7
|
+
def test_nil
|
8
|
+
input = nil
|
9
|
+
expected = {}
|
10
|
+
actual = ActiveModel::Serializer::Utils.include_args_to_hash(input)
|
11
|
+
assert_equal(expected, actual)
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_empty_string
|
15
|
+
input = ''
|
16
|
+
expected = {}
|
17
|
+
actual = ActiveModel::Serializer::Utils.include_args_to_hash(input)
|
18
|
+
assert_equal(expected, actual)
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_single_string
|
22
|
+
input = 'author'
|
23
|
+
expected = { author: {} }
|
24
|
+
actual = ActiveModel::Serializer::Utils.include_args_to_hash(input)
|
25
|
+
assert_equal(expected, actual)
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_multiple_strings
|
29
|
+
input = 'author,comments'
|
30
|
+
expected = { author: {}, comments: {} }
|
31
|
+
actual = ActiveModel::Serializer::Utils.include_args_to_hash(input)
|
32
|
+
assert_equal(expected, actual)
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_multiple_strings_with_space
|
36
|
+
input = 'author, comments'
|
37
|
+
expected = { author: {}, comments: {} }
|
38
|
+
actual = ActiveModel::Serializer::Utils.include_args_to_hash(input)
|
39
|
+
assert_equal(expected, actual)
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_nested_string
|
43
|
+
input = 'posts.author'
|
44
|
+
expected = { posts: { author: {} } }
|
45
|
+
actual = ActiveModel::Serializer::Utils.include_args_to_hash(input)
|
46
|
+
assert_equal(expected, actual)
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_multiple_nested_string
|
50
|
+
input = 'posts.author,posts.comments.author,comments'
|
51
|
+
expected = { posts: { author: {}, comments: { author: {} } }, comments: {} }
|
52
|
+
actual = ActiveModel::Serializer::Utils.include_args_to_hash(input)
|
53
|
+
assert_equal(expected, actual)
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_empty_array
|
57
|
+
input = []
|
58
|
+
expected = {}
|
59
|
+
actual = ActiveModel::Serializer::Utils.include_args_to_hash(input)
|
60
|
+
assert_equal(expected, actual)
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_simple_array
|
64
|
+
input = [:comments, :author]
|
65
|
+
expected = { author: {}, comments: {} }
|
66
|
+
actual = ActiveModel::Serializer::Utils.include_args_to_hash(input)
|
67
|
+
assert_equal(expected, actual)
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_nested_array
|
71
|
+
input = [:comments, posts: [:author, comments: [:author]]]
|
72
|
+
expected = { posts: { author: {}, comments: { author: {} } }, comments: {} }
|
73
|
+
actual = ActiveModel::Serializer::Utils.include_args_to_hash(input)
|
74
|
+
assert_equal(expected, actual)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cheap_ams
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.10.
|
4
|
+
version: 0.10.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steve Klabnik
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-09-
|
11
|
+
date: 2015-09-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -160,6 +160,7 @@ files:
|
|
160
160
|
- lib/active_model/serializer/railtie.rb
|
161
161
|
- lib/active_model/serializer/reflection.rb
|
162
162
|
- lib/active_model/serializer/singular_reflection.rb
|
163
|
+
- lib/active_model/serializer/utils.rb
|
163
164
|
- lib/active_model/serializer/version.rb
|
164
165
|
- lib/active_model_serializers.rb
|
165
166
|
- lib/generators/serializer/USAGE
|
@@ -173,6 +174,7 @@ files:
|
|
173
174
|
- test/action_controller/json_api/pagination_test.rb
|
174
175
|
- test/action_controller/serialization_scope_name_test.rb
|
175
176
|
- test/action_controller/serialization_test.rb
|
177
|
+
- test/active_record_test.rb
|
176
178
|
- test/adapter/fragment_cache_test.rb
|
177
179
|
- test/adapter/json/belongs_to_test.rb
|
178
180
|
- test/adapter/json/collection_test.rb
|
@@ -217,6 +219,7 @@ files:
|
|
217
219
|
- test/support/stream_capture.rb
|
218
220
|
- test/support/test_case.rb
|
219
221
|
- test/test_helper.rb
|
222
|
+
- test/utils/include_args_to_hash_test.rb
|
220
223
|
homepage: https://github.com/rails-api/active_model_serializers
|
221
224
|
licenses:
|
222
225
|
- MIT
|
@@ -248,6 +251,7 @@ test_files:
|
|
248
251
|
- test/action_controller/json_api/pagination_test.rb
|
249
252
|
- test/action_controller/serialization_scope_name_test.rb
|
250
253
|
- test/action_controller/serialization_test.rb
|
254
|
+
- test/active_record_test.rb
|
251
255
|
- test/adapter/fragment_cache_test.rb
|
252
256
|
- test/adapter/json/belongs_to_test.rb
|
253
257
|
- test/adapter/json/collection_test.rb
|
@@ -292,3 +296,4 @@ test_files:
|
|
292
296
|
- test/support/stream_capture.rb
|
293
297
|
- test/support/test_case.rb
|
294
298
|
- test/test_helper.rb
|
299
|
+
- test/utils/include_args_to_hash_test.rb
|