active_model_serializers 0.9.0.alpha1 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +132 -15
- data/lib/action_controller/serialization.rb +5 -0
- data/lib/action_controller/serialization_test_case.rb +79 -0
- data/lib/active_model/array_serializer.rb +15 -8
- data/lib/active_model/default_serializer.rb +12 -2
- data/lib/active_model/serializable.rb +21 -6
- data/lib/active_model/serializer.rb +84 -9
- data/lib/active_model/serializer/associations.rb +38 -11
- data/lib/active_model/serializer/generators/serializer/serializer_generator.rb +1 -1
- data/lib/active_model/serializer/version.rb +1 -1
- data/lib/active_model_serializers.rb +6 -2
- data/test/fixtures/poro.rb +11 -0
- data/test/integration/action_controller/serialization_test.rb +53 -0
- data/test/integration/action_controller/serialization_test_case_test.rb +61 -0
- data/test/integration/active_record/active_record_test.rb +1 -1
- data/test/integration/generators/scaffold_controller_generator_test.rb +0 -3
- data/test/test_helper.rb +4 -1
- data/test/unit/active_model/array_serializer/except_test.rb +18 -0
- data/test/unit/active_model/array_serializer/key_format_test.rb +18 -0
- data/test/unit/active_model/array_serializer/meta_test.rb +1 -1
- data/test/unit/active_model/array_serializer/only_test.rb +18 -0
- data/test/unit/active_model/array_serializer/root_test.rb +2 -2
- data/test/unit/active_model/array_serializer/scope_test.rb +1 -1
- data/test/unit/active_model/array_serializer/serialization_test.rb +120 -4
- data/test/unit/active_model/default_serializer_test.rb +1 -1
- data/test/unit/active_model/serializer/associations/build_serializer_test.rb +1 -1
- data/test/unit/active_model/serializer/associations_test.rb +1 -1
- data/test/unit/active_model/serializer/attributes_test.rb +1 -1
- data/test/unit/active_model/serializer/config_test.rb +7 -5
- data/test/unit/active_model/serializer/filter_test.rb +22 -2
- data/test/unit/active_model/serializer/has_many_test.rb +61 -4
- data/test/unit/active_model/serializer/has_one_test.rb +59 -3
- data/test/unit/active_model/serializer/key_format_test.rb +25 -0
- data/test/unit/active_model/serializer/meta_test.rb +1 -1
- data/test/unit/active_model/serializer/options_test.rb +15 -0
- data/test/unit/active_model/serializer/root_test.rb +2 -2
- data/test/unit/active_model/serializer/scope_test.rb +3 -3
- metadata +36 -27
- data/test/coverage_setup.rb +0 -15
- data/test/tmp/app/serializers/account_serializer.rb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 65701e1dd4ae30a60340c60fa9361c540148bb64
|
4
|
+
data.tar.gz: f7b2b52348b116ac1eea607a51e9ddb8d9c15fce
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 658d1fadb66a26b4b93a72cdb87498bb89ee83565de5d846ca3e2cdaa913303256e9267627d8e55593aa1696963f255e2fe44918e858ce2e66251710d3694241
|
7
|
+
data.tar.gz: 2b100c2bcb26d9696001eefae6fd3bddc68d779578c2c313f64b06f47cf51024f6e525a7afd70d8afd28d973bb7fd2d9bb7923391d2271233317d2a6669948b0
|
data/README.md
CHANGED
@@ -1,15 +1,8 @@
|
|
1
|
-
[![Build Status](https://api.travis-ci.org/rails-api/active_model_serializers.png)](https://travis-ci.org/rails-api/active_model_serializers)
|
1
|
+
[![Build Status](https://api.travis-ci.org/rails-api/active_model_serializers.png?branch=0-9-stable)](https://travis-ci.org/rails-api/active_model_serializers)
|
2
2
|
[![Code Climate](https://codeclimate.com/github/rails-api/active_model_serializers.png)](https://codeclimate.com/github/rails-api/active_model_serializers)
|
3
|
-
[![Coverage Status](https://coveralls.io/repos/rails-api/active_model_serializers/badge.png?branch=master)](https://coveralls.io/r/rails-api/active_model_serializers)
|
4
3
|
|
5
4
|
# ActiveModel::Serializers
|
6
5
|
|
7
|
-
## Master - 0.9.0
|
8
|
-
|
9
|
-
**master is under development, there are some incompatible changes with the current stable release.**
|
10
|
-
|
11
|
-
If you want to read the stable documentation visit [0.8 README](https://github.com/rails-api/active_model_serializers/blob/0-8-stable/README.md)
|
12
|
-
|
13
6
|
## Purpose
|
14
7
|
|
15
8
|
`ActiveModel::Serializers` encapsulates the JSON serialization of objects.
|
@@ -67,13 +60,11 @@ $ rails g serializer post
|
|
67
60
|
|
68
61
|
### Support for POROs
|
69
62
|
|
70
|
-
|
71
|
-
|
72
|
-
your POROs supported.
|
63
|
+
The PORO should include ActiveModel::SerializerSupport. That's all you need to
|
64
|
+
do to have your POROs supported.
|
73
65
|
|
74
|
-
|
75
|
-
|
76
|
-
All new serializers descend from ActiveModel::Serializer
|
66
|
+
For Rails versions before Rails 4 ActiveModel::Serializers expects objects to
|
67
|
+
implement `read_attribute_for_serialization`.
|
77
68
|
|
78
69
|
# render :json
|
79
70
|
|
@@ -158,6 +149,29 @@ To specify a custom serializer for the items within an array:
|
|
158
149
|
render json: @posts, each_serializer: FancyPostSerializer
|
159
150
|
```
|
160
151
|
|
152
|
+
## Render independently
|
153
|
+
|
154
|
+
By default the setting of serializer is in controller as described above which is the
|
155
|
+
recommended way. However, there may be cases you need to render the json object elsewhere
|
156
|
+
say in a helper or a view when controller is only for main object.
|
157
|
+
|
158
|
+
Then you can render the serialized JSON independently.
|
159
|
+
|
160
|
+
```ruby
|
161
|
+
def current_user_as_json_helper
|
162
|
+
CurrentUserSerializer.new(current_user).to_json
|
163
|
+
end
|
164
|
+
```
|
165
|
+
|
166
|
+
You can also render an array of objects using ArraySerializer.
|
167
|
+
|
168
|
+
```ruby
|
169
|
+
def users_array_as_json_helper(users)
|
170
|
+
ActiveModel::ArraySerializer.new(users, each_serializer: UserSerializer).to_json
|
171
|
+
end
|
172
|
+
```
|
173
|
+
|
174
|
+
|
161
175
|
## Disabling the root element
|
162
176
|
|
163
177
|
You have 4 options to disable the root element, each with a slightly different scope:
|
@@ -205,6 +219,23 @@ def default_serializer_options
|
|
205
219
|
end
|
206
220
|
```
|
207
221
|
|
222
|
+
## Changing the Key Format
|
223
|
+
|
224
|
+
You can specify that serializers use the lower-camel key format at the config, class or instance level.
|
225
|
+
|
226
|
+
```ruby
|
227
|
+
|
228
|
+
ActiveModel::Serializer.setup do |config|
|
229
|
+
config.key_format = :lower_camel
|
230
|
+
end
|
231
|
+
|
232
|
+
class BlogLowerCamelSerializer < ActiveModel::Serializer
|
233
|
+
format_keys :lower_camel
|
234
|
+
end
|
235
|
+
|
236
|
+
BlogSerializer.new(object, key_format: :lower_camel)
|
237
|
+
```
|
238
|
+
|
208
239
|
## Getting the old version
|
209
240
|
|
210
241
|
If you find that your project is already relying on the old rails to_json
|
@@ -263,7 +294,7 @@ authorization context to your serializer. By default, the context
|
|
263
294
|
is the current user of your application, but this
|
264
295
|
[can be customized](#customizing-scope).
|
265
296
|
|
266
|
-
Serializers
|
297
|
+
Serializers provide a method named `filter`, which should return an array
|
267
298
|
used to determine what attributes and associations should be included in the output.
|
268
299
|
This is typically used to customize output based on `current_user`. For example:
|
269
300
|
|
@@ -485,6 +516,33 @@ Now, any associations will be supplied as an Array of IDs:
|
|
485
516
|
}
|
486
517
|
```
|
487
518
|
|
519
|
+
You may also choose to embed the IDs by the association's name underneath an
|
520
|
+
`embed_key` for the resource. For example, say we want to change `comment_ids`
|
521
|
+
to `comments` underneath a `links` key:
|
522
|
+
|
523
|
+
```ruby
|
524
|
+
class PostSerializer < ActiveModel::Serializer
|
525
|
+
attributes :id, :title, :body
|
526
|
+
|
527
|
+
has_many :comments, embed: ids, embed_namespace: :links
|
528
|
+
end
|
529
|
+
```
|
530
|
+
|
531
|
+
The JSON will look like this:
|
532
|
+
|
533
|
+
```json
|
534
|
+
{
|
535
|
+
"post": {
|
536
|
+
"id": 1,
|
537
|
+
"title": "New post",
|
538
|
+
"body": "A body!",
|
539
|
+
"links": {
|
540
|
+
"comments": [ 1, 2, 3 ]
|
541
|
+
}
|
542
|
+
}
|
543
|
+
}
|
544
|
+
```
|
545
|
+
|
488
546
|
Alternatively, you can choose to embed only the ids or the associated objects per association:
|
489
547
|
|
490
548
|
```ruby
|
@@ -552,6 +610,42 @@ this:
|
|
552
610
|
}
|
553
611
|
```
|
554
612
|
|
613
|
+
If you would like to namespace association JSON underneath a certain key in
|
614
|
+
the root document (say, `linked`), you can specify an `embed_in_root_key`:
|
615
|
+
|
616
|
+
```ruby
|
617
|
+
class PostSerializer < ActiveModel::Serializer
|
618
|
+
embed: ids, include: true, embed_in_root_key: :linked
|
619
|
+
|
620
|
+
attributes: :id, :title, :body
|
621
|
+
has_many :comments, :tags
|
622
|
+
end
|
623
|
+
```
|
624
|
+
|
625
|
+
The above would yield the following JSON document:
|
626
|
+
|
627
|
+
```json
|
628
|
+
{
|
629
|
+
"post": {
|
630
|
+
"id": 1,
|
631
|
+
"title": "New post",
|
632
|
+
"body": "A body!",
|
633
|
+
"comment_ids": [ 1, 2 ]
|
634
|
+
},
|
635
|
+
"linked": {
|
636
|
+
"comments": [
|
637
|
+
{ "id": 1, "body": "what a dumb post", "tag_ids": [ 1, 2 ] },
|
638
|
+
{ "id": 2, "body": "i liked it", "tag_ids": [ 1, 3 ] },
|
639
|
+
],
|
640
|
+
"tags": [
|
641
|
+
{ "id": 1, "name": "short" },
|
642
|
+
{ "id": 2, "name": "whiny" },
|
643
|
+
{ "id": 3, "name": "happy" }
|
644
|
+
]
|
645
|
+
}
|
646
|
+
}
|
647
|
+
```
|
648
|
+
|
555
649
|
When side-loading data, your serializer cannot have the `{ root: false }` option,
|
556
650
|
as this would lead to invalid JSON. If you do not have a root key, the `include`
|
557
651
|
instruction will be ignored
|
@@ -724,6 +818,29 @@ end
|
|
724
818
|
|
725
819
|
The caching interface uses `Rails.cache` under the hood.
|
726
820
|
|
821
|
+
# ApplicationSerializer
|
822
|
+
|
823
|
+
By default, new serializers descend from ActiveModel::Serializer. However, if you wish to share behaviour across your serializers you can create an ApplicationSerializer at ```app/serializers/application_serializer.rb```:
|
824
|
+
|
825
|
+
```ruby
|
826
|
+
class ApplicationSerializer < ActiveModel::Serializer
|
827
|
+
end
|
828
|
+
```
|
829
|
+
|
830
|
+
Any newly generated serializers will automatically descend from ApplicationSerializer.
|
831
|
+
|
832
|
+
```
|
833
|
+
$ rails g serializer post
|
834
|
+
```
|
835
|
+
|
836
|
+
now generates:
|
837
|
+
|
838
|
+
```ruby
|
839
|
+
class PostSerializer < ApplicationSerializer
|
840
|
+
attributes :id
|
841
|
+
end
|
842
|
+
````
|
843
|
+
|
727
844
|
# Design and Implementation Guidelines
|
728
845
|
|
729
846
|
## Keep it Simple
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module ActionController
|
2
|
+
module SerializationAssertions
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
setup :setup_subscriptions
|
7
|
+
teardown :teardown_subscriptions
|
8
|
+
end
|
9
|
+
|
10
|
+
def setup_subscriptions
|
11
|
+
@serializers = Hash.new(0)
|
12
|
+
|
13
|
+
ActiveSupport::Notifications.subscribe("!serialize.active_model_serializers") do |name, start, finish, id, payload|
|
14
|
+
serializer = payload[:serializer]
|
15
|
+
@serializers[serializer] += 1
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def teardown_subscriptions
|
20
|
+
ActiveSupport::Notifications.unsubscribe("!serialize.active_model_serializers")
|
21
|
+
end
|
22
|
+
|
23
|
+
def process(*args)
|
24
|
+
@serializers = Hash.new(0)
|
25
|
+
super
|
26
|
+
end
|
27
|
+
|
28
|
+
# Asserts that the request was rendered with the appropriate serializers.
|
29
|
+
#
|
30
|
+
# # assert that the "PostSerializer" serializer was rendered
|
31
|
+
# assert_serializer "PostSerializer"
|
32
|
+
#
|
33
|
+
# # assert that the instance of PostSerializer was rendered
|
34
|
+
# assert_serializer PostSerializer
|
35
|
+
#
|
36
|
+
# # assert that the "PostSerializer" serializer was rendered
|
37
|
+
# assert_serializer :post_serializer
|
38
|
+
#
|
39
|
+
# # assert that the rendered serializer starts with "Post"
|
40
|
+
# assert_serializer %r{\APost.+\Z}
|
41
|
+
#
|
42
|
+
# # assert that no serializer was rendered
|
43
|
+
# assert_serializer nil
|
44
|
+
#
|
45
|
+
#
|
46
|
+
def assert_serializer(options = {}, message = nil)
|
47
|
+
# Force body to be read in case the template is being streamed.
|
48
|
+
response.body
|
49
|
+
|
50
|
+
rendered = @serializers
|
51
|
+
msg = message || "expecting <#{options.inspect}> but rendering with <#{rendered.keys}>"
|
52
|
+
|
53
|
+
matches_serializer = case options
|
54
|
+
when lambda { |options| options.kind_of?(Class) && options < ActiveModel::Serializer }
|
55
|
+
rendered.any? do |serializer, count|
|
56
|
+
options.name == serializer
|
57
|
+
end
|
58
|
+
when Symbol
|
59
|
+
options = options.to_s.camelize
|
60
|
+
rendered.any? do |serializer, count|
|
61
|
+
serializer == options
|
62
|
+
end
|
63
|
+
when String
|
64
|
+
!options.empty? && rendered.any? do |serializer, count|
|
65
|
+
serializer == options
|
66
|
+
end
|
67
|
+
when Regexp
|
68
|
+
rendered.any? do |serializer, count|
|
69
|
+
serializer.match(options)
|
70
|
+
end
|
71
|
+
when NilClass
|
72
|
+
rendered.blank?
|
73
|
+
else
|
74
|
+
raise ArgumentError, "assert_serializer only accepts a String, Symbol, Regexp, ActiveModel::Serializer, or nil"
|
75
|
+
end
|
76
|
+
assert matches_serializer, msg
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'active_model/default_serializer'
|
2
2
|
require 'active_model/serializable'
|
3
|
-
require 'active_model/serializer'
|
4
3
|
|
5
4
|
module ActiveModel
|
6
5
|
class ArraySerializer
|
@@ -20,20 +19,21 @@ module ActiveModel
|
|
20
19
|
@meta = options[@meta_key]
|
21
20
|
@each_serializer = options[:each_serializer]
|
22
21
|
@resource_name = options[:resource_name]
|
22
|
+
@only = options[:only] ? Array(options[:only]) : nil
|
23
|
+
@except = options[:except] ? Array(options[:except]) : nil
|
24
|
+
@key_format = options[:key_format] || options[:each_serializer].try(:key_format)
|
23
25
|
end
|
24
|
-
attr_accessor :object, :scope, :root, :meta_key, :meta
|
26
|
+
attr_accessor :object, :scope, :root, :meta_key, :meta, :key_format
|
25
27
|
|
26
28
|
def json_key
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
root
|
31
|
-
end
|
29
|
+
key = root.nil? ? @resource_name : root
|
30
|
+
|
31
|
+
key_format == :lower_camel && key.present? ? key.camelize(:lower) : key
|
32
32
|
end
|
33
33
|
|
34
34
|
def serializer_for(item)
|
35
35
|
serializer_class = @each_serializer || Serializer.serializer_for(item) || DefaultSerializer
|
36
|
-
serializer_class.new(item, scope: scope)
|
36
|
+
serializer_class.new(item, scope: scope, key_format: key_format, only: @only, except: @except)
|
37
37
|
end
|
38
38
|
|
39
39
|
def serializable_object
|
@@ -46,6 +46,8 @@ module ActiveModel
|
|
46
46
|
def embedded_in_root_associations
|
47
47
|
@object.each_with_object({}) do |item, hash|
|
48
48
|
serializer_for(item).embedded_in_root_associations.each_pair do |type, objects|
|
49
|
+
next if !objects || objects.flatten.empty?
|
50
|
+
|
49
51
|
if hash.has_key?(type)
|
50
52
|
hash[type].concat(objects).uniq!
|
51
53
|
else
|
@@ -54,5 +56,10 @@ module ActiveModel
|
|
54
56
|
end
|
55
57
|
end
|
56
58
|
end
|
59
|
+
|
60
|
+
private
|
61
|
+
def instrumentation_keys
|
62
|
+
[:object, :scope, :root, :meta_key, :meta, :each_serializer, :resource_name, :key_format]
|
63
|
+
end
|
57
64
|
end
|
58
65
|
end
|
@@ -9,14 +9,24 @@ module ActiveModel
|
|
9
9
|
|
10
10
|
attr_reader :object
|
11
11
|
|
12
|
-
def initialize(object, options=
|
12
|
+
def initialize(object, options={})
|
13
13
|
@object = object
|
14
|
+
@wrap_in_array = options[:_wrap_in_array]
|
14
15
|
end
|
15
16
|
|
16
17
|
def as_json(options={})
|
17
|
-
|
18
|
+
instrument('!serialize') do
|
19
|
+
return [] if @object.nil? && @wrap_in_array
|
20
|
+
hash = @object.as_json
|
21
|
+
@wrap_in_array ? [hash] : hash
|
22
|
+
end
|
18
23
|
end
|
19
24
|
alias serializable_hash as_json
|
20
25
|
alias serializable_object as_json
|
26
|
+
|
27
|
+
private
|
28
|
+
def instrumentation_keys
|
29
|
+
[:object, :wrap_in_array]
|
30
|
+
end
|
21
31
|
end
|
22
32
|
end
|
@@ -1,12 +1,14 @@
|
|
1
1
|
module ActiveModel
|
2
2
|
module Serializable
|
3
3
|
def as_json(options={})
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
instrument('!serialize') do
|
5
|
+
if root = options.fetch(:root, json_key)
|
6
|
+
hash = { root => serializable_object }
|
7
|
+
hash.merge!(serializable_data)
|
8
|
+
hash
|
9
|
+
else
|
10
|
+
serializable_object
|
11
|
+
end
|
10
12
|
end
|
11
13
|
end
|
12
14
|
|
@@ -21,5 +23,18 @@ module ActiveModel
|
|
21
23
|
def embedded_in_root_associations
|
22
24
|
{}
|
23
25
|
end
|
26
|
+
|
27
|
+
private
|
28
|
+
def instrument(action, &block)
|
29
|
+
payload = instrumentation_keys.inject({ serializer: self.class.name }) do |payload, key|
|
30
|
+
payload[:payload] = self.instance_variable_get(:"@#{key}")
|
31
|
+
payload
|
32
|
+
end
|
33
|
+
ActiveSupport::Notifications.instrument("#{action}.active_model_serializers", payload, &block)
|
34
|
+
end
|
35
|
+
|
36
|
+
def instrumentation_keys
|
37
|
+
[:object, :scope, :root, :meta_key, :meta, :wrap_in_array, :only, :except, :key_format]
|
38
|
+
end
|
24
39
|
end
|
25
40
|
end
|
@@ -24,9 +24,21 @@ module ActiveModel
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
+
EMBED_IN_ROOT_OPTIONS = [
|
28
|
+
:include,
|
29
|
+
:embed_in_root,
|
30
|
+
:embed_in_root_key,
|
31
|
+
:embed_namespace
|
32
|
+
].freeze
|
33
|
+
|
27
34
|
def embed(type, options={})
|
28
35
|
CONFIG.embed = type
|
29
|
-
|
36
|
+
if EMBED_IN_ROOT_OPTIONS.any? { |opt| options[opt].present? }
|
37
|
+
CONFIG.embed_in_root = true
|
38
|
+
end
|
39
|
+
if options[:embed_in_root_key].present?
|
40
|
+
CONFIG.embed_in_root_key = options[:embed_in_root_key]
|
41
|
+
end
|
30
42
|
ActiveSupport::Deprecation.warn <<-WARN
|
31
43
|
** Notice: embed is deprecated. **
|
32
44
|
The use of .embed method on a Serializer will be soon removed, as this should have a global scope and not a class scope.
|
@@ -38,10 +50,19 @@ end
|
|
38
50
|
WARN
|
39
51
|
end
|
40
52
|
|
53
|
+
def format_keys(format)
|
54
|
+
@key_format = format
|
55
|
+
end
|
56
|
+
attr_reader :key_format
|
57
|
+
|
41
58
|
if RUBY_VERSION >= '2.0'
|
42
59
|
def serializer_for(resource)
|
43
60
|
if resource.respond_to?(:to_ary)
|
44
|
-
ArraySerializer
|
61
|
+
if Object.constants.include?(:ArraySerializer)
|
62
|
+
::ArraySerializer
|
63
|
+
else
|
64
|
+
ArraySerializer
|
65
|
+
end
|
45
66
|
else
|
46
67
|
begin
|
47
68
|
Object.const_get "#{resource.class.name}Serializer"
|
@@ -53,7 +74,11 @@ end
|
|
53
74
|
else
|
54
75
|
def serializer_for(resource)
|
55
76
|
if resource.respond_to?(:to_ary)
|
56
|
-
ArraySerializer
|
77
|
+
if Object.constants.include?(:ArraySerializer)
|
78
|
+
::ArraySerializer
|
79
|
+
else
|
80
|
+
ArraySerializer
|
81
|
+
end
|
57
82
|
else
|
58
83
|
"#{resource.class.name}Serializer".safe_constantize
|
59
84
|
end
|
@@ -108,15 +133,21 @@ end
|
|
108
133
|
@meta_key = options[:meta_key] || :meta
|
109
134
|
@meta = options[@meta_key]
|
110
135
|
@wrap_in_array = options[:_wrap_in_array]
|
136
|
+
@only = options[:only] ? Array(options[:only]) : nil
|
137
|
+
@except = options[:except] ? Array(options[:except]) : nil
|
138
|
+
@key_format = options[:key_format]
|
139
|
+
@context = options[:context]
|
111
140
|
end
|
112
|
-
attr_accessor :object, :scope, :root, :meta_key, :meta
|
141
|
+
attr_accessor :object, :scope, :root, :meta_key, :meta, :key_format, :context
|
113
142
|
|
114
143
|
def json_key
|
115
|
-
if root == true || root.nil?
|
144
|
+
key = if root == true || root.nil?
|
116
145
|
self.class.root_name
|
117
146
|
else
|
118
147
|
root
|
119
148
|
end
|
149
|
+
|
150
|
+
key_format == :lower_camel && key.present? ? key.camelize(:lower) : key
|
120
151
|
end
|
121
152
|
|
122
153
|
def attributes
|
@@ -131,8 +162,17 @@ end
|
|
131
162
|
associations.each_with_object({}) do |(name, association), hash|
|
132
163
|
if included_associations.include? name
|
133
164
|
if association.embed_ids?
|
134
|
-
|
165
|
+
ids = serialize_ids association
|
166
|
+
if association.embed_namespace?
|
167
|
+
hash = hash[association.embed_namespace] ||= {}
|
168
|
+
hash[association.key] = ids
|
169
|
+
else
|
170
|
+
hash[association.key] = ids
|
171
|
+
end
|
135
172
|
elsif association.embed_objects?
|
173
|
+
if association.embed_namespace?
|
174
|
+
hash = hash[association.embed_namespace] ||= {}
|
175
|
+
end
|
136
176
|
hash[association.embedded_key] = serialize association
|
137
177
|
end
|
138
178
|
end
|
@@ -140,7 +180,13 @@ end
|
|
140
180
|
end
|
141
181
|
|
142
182
|
def filter(keys)
|
143
|
-
|
183
|
+
if @only
|
184
|
+
keys & @only
|
185
|
+
elsif @except
|
186
|
+
keys - @except
|
187
|
+
else
|
188
|
+
keys
|
189
|
+
end
|
144
190
|
end
|
145
191
|
|
146
192
|
def embedded_in_root_associations
|
@@ -149,8 +195,11 @@ end
|
|
149
195
|
associations.each_with_object({}) do |(name, association), hash|
|
150
196
|
if included_associations.include? name
|
151
197
|
if association.embed_in_root?
|
198
|
+
if association.embed_in_root_key?
|
199
|
+
hash = hash[association.embed_in_root_key] ||= {}
|
200
|
+
end
|
152
201
|
association_serializer = build_serializer(association)
|
153
|
-
hash.merge!
|
202
|
+
hash.merge!(association_serializer.embedded_in_root_associations) {|key, oldval, newval| [newval, oldval].flatten }
|
154
203
|
|
155
204
|
serialized_data = association_serializer.serializable_object
|
156
205
|
key = association.root_key
|
@@ -182,12 +231,38 @@ end
|
|
182
231
|
end
|
183
232
|
end
|
184
233
|
|
234
|
+
def key_format
|
235
|
+
@key_format || self.class.key_format || CONFIG.key_format
|
236
|
+
end
|
237
|
+
|
238
|
+
def format_key(key)
|
239
|
+
if key_format == :lower_camel
|
240
|
+
key.to_s.camelize(:lower)
|
241
|
+
else
|
242
|
+
key
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
def convert_keys(hash)
|
247
|
+
Hash[hash.map do |k,v|
|
248
|
+
key = if k.is_a?(Symbol)
|
249
|
+
format_key(k).to_sym
|
250
|
+
else
|
251
|
+
format_key(k)
|
252
|
+
end
|
253
|
+
|
254
|
+
[key ,v]
|
255
|
+
end]
|
256
|
+
end
|
257
|
+
|
185
258
|
def serializable_object(options={})
|
186
|
-
return nil if object.nil?
|
259
|
+
return @wrap_in_array ? [] : nil if @object.nil?
|
187
260
|
hash = attributes
|
188
261
|
hash.merge! associations
|
262
|
+
hash = convert_keys(hash) if key_format.present?
|
189
263
|
@wrap_in_array ? [hash] : hash
|
190
264
|
end
|
191
265
|
alias_method :serializable_hash, :serializable_object
|
192
266
|
end
|
267
|
+
|
193
268
|
end
|