cheap_ams 0.10.8 → 0.10.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
-
[](https://travis-ci.org/rails-api/active_model_serializers)
|
3
|
+
[](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
|