active_model_serializers 0.9.0.alpha1 → 0.9.0
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/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
|
-
[](https://travis-ci.org/rails-api/active_model_serializers)
|
1
|
+
[](https://travis-ci.org/rails-api/active_model_serializers)
|
2
2
|
[](https://codeclimate.com/github/rails-api/active_model_serializers)
|
3
|
-
[](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
|