active_model_serializers 0.8.3 → 0.9.2
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/CHANGELOG.md +25 -5
- data/CONTRIBUTING.md +20 -0
- data/DESIGN.textile +4 -4
- data/{MIT-LICENSE.txt → MIT-LICENSE} +0 -0
- data/README.md +307 -99
- data/lib/action_controller/serialization.rb +35 -16
- data/lib/action_controller/serialization_test_case.rb +79 -0
- data/lib/active_model/array_serializer.rb +40 -79
- data/lib/active_model/default_serializer.rb +32 -0
- data/lib/active_model/serializable.rb +40 -0
- data/lib/active_model/serializer/associations.rb +71 -202
- data/lib/active_model/serializer/config.rb +31 -0
- data/lib/active_model/serializer/generators/resource_override.rb +13 -0
- data/lib/{generators → active_model/serializer/generators}/serializer/USAGE +0 -0
- data/lib/active_model/serializer/generators/serializer/scaffold_controller_generator.rb +14 -0
- data/lib/active_model/serializer/generators/serializer/serializer_generator.rb +37 -0
- data/lib/active_model/serializer/generators/serializer/templates/controller.rb +93 -0
- data/lib/active_model/serializer/generators/serializer/templates/serializer.rb +8 -0
- data/lib/active_model/serializer/railtie.rb +10 -0
- data/lib/active_model/{serializers → serializer}/version.rb +1 -1
- data/lib/active_model/serializer.rb +186 -433
- data/lib/active_model/serializer_support.rb +5 -0
- data/lib/active_model_serializers.rb +13 -88
- data/test/fixtures/active_record.rb +92 -0
- data/test/fixtures/poro.rb +75 -0
- data/test/integration/action_controller/serialization_test.rb +287 -0
- data/test/integration/action_controller/serialization_test_case_test.rb +61 -0
- data/test/integration/active_record/active_record_test.rb +77 -0
- data/test/integration/generators/resource_generator_test.rb +26 -0
- data/test/integration/generators/scaffold_controller_generator_test.rb +64 -0
- data/test/integration/generators/serializer_generator_test.rb +41 -0
- data/test/test_app.rb +11 -0
- data/test/test_helper.rb +10 -18
- data/test/tmp/app/serializers/account_serializer.rb +3 -0
- 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 +53 -0
- data/test/unit/active_model/array_serializer/only_test.rb +18 -0
- data/test/unit/active_model/array_serializer/root_test.rb +102 -0
- data/test/unit/active_model/array_serializer/scope_test.rb +24 -0
- data/test/unit/active_model/array_serializer/serialization_test.rb +199 -0
- data/test/unit/active_model/default_serializer_test.rb +13 -0
- data/test/unit/active_model/serializer/associations/build_serializer_test.rb +21 -0
- data/test/unit/active_model/serializer/associations_test.rb +19 -0
- data/test/unit/active_model/serializer/attributes_test.rb +41 -0
- data/test/unit/active_model/serializer/config_test.rb +88 -0
- data/test/unit/active_model/serializer/filter_test.rb +69 -0
- data/test/unit/active_model/serializer/has_many_test.rb +230 -0
- data/test/unit/active_model/serializer/has_one_test.rb +207 -0
- data/test/unit/active_model/serializer/key_format_test.rb +25 -0
- data/test/unit/active_model/serializer/meta_test.rb +39 -0
- data/test/unit/active_model/serializer/options_test.rb +15 -0
- data/test/unit/active_model/serializer/root_test.rb +117 -0
- data/test/unit/active_model/serializer/scope_test.rb +49 -0
- metadata +88 -62
- data/.gitignore +0 -18
- data/.travis.yml +0 -28
- data/Gemfile +0 -4
- data/Gemfile.edge +0 -9
- data/Rakefile +0 -18
- data/active_model_serializers.gemspec +0 -24
- data/bench/perf.rb +0 -43
- data/cruft.md +0 -19
- data/lib/active_record/serializer_override.rb +0 -16
- data/lib/generators/resource_override.rb +0 -13
- data/lib/generators/serializer/serializer_generator.rb +0 -42
- data/lib/generators/serializer/templates/serializer.rb +0 -19
- data/test/array_serializer_test.rb +0 -75
- data/test/association_test.rb +0 -592
- data/test/caching_test.rb +0 -96
- data/test/generators_test.rb +0 -85
- data/test/no_serialization_scope_test.rb +0 -34
- data/test/serialization_scope_name_test.rb +0 -67
- data/test/serialization_test.rb +0 -392
- data/test/serializer_support_test.rb +0 -51
- data/test/serializer_test.rb +0 -1465
- data/test/test_fakes.rb +0 -217
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'active_support/core_ext/class/attribute'
|
2
|
+
|
1
3
|
module ActionController
|
2
4
|
# Action Controller Serialization
|
3
5
|
#
|
@@ -27,34 +29,51 @@ module ActionController
|
|
27
29
|
|
28
30
|
include ActionController::Renderers
|
29
31
|
|
32
|
+
class << self
|
33
|
+
attr_accessor :enabled
|
34
|
+
end
|
35
|
+
self.enabled = true
|
36
|
+
|
30
37
|
included do
|
31
38
|
class_attribute :_serialization_scope
|
32
39
|
self._serialization_scope = :current_user
|
33
40
|
end
|
34
41
|
|
35
|
-
|
36
|
-
|
37
|
-
|
42
|
+
module ClassMethods
|
43
|
+
def serialization_scope(scope)
|
44
|
+
self._serialization_scope = scope
|
45
|
+
end
|
38
46
|
end
|
39
47
|
|
40
|
-
def
|
48
|
+
def _render_option_json(resource, options)
|
49
|
+
serializer = build_json_serializer(resource, options)
|
50
|
+
|
51
|
+
if serializer
|
52
|
+
super(serializer, options)
|
53
|
+
else
|
54
|
+
super
|
55
|
+
end
|
41
56
|
end
|
42
57
|
|
43
|
-
|
44
|
-
define_method renderer_method do |resource, options|
|
45
|
-
json = ActiveModel::Serializer.build_json(self, resource, options)
|
58
|
+
private
|
46
59
|
|
47
|
-
|
48
|
-
|
49
|
-
else
|
50
|
-
super(resource, options)
|
51
|
-
end
|
52
|
-
end
|
60
|
+
def default_serializer_options
|
61
|
+
{}
|
53
62
|
end
|
54
63
|
|
55
|
-
|
56
|
-
|
57
|
-
|
64
|
+
def serialization_scope
|
65
|
+
_serialization_scope = self.class._serialization_scope
|
66
|
+
send(_serialization_scope) if _serialization_scope && respond_to?(_serialization_scope, true)
|
67
|
+
end
|
68
|
+
|
69
|
+
def build_json_serializer(resource, options = {})
|
70
|
+
options = default_serializer_options.merge(options)
|
71
|
+
|
72
|
+
if serializer = options.fetch(:serializer, ActiveModel::Serializer.serializer_for(resource))
|
73
|
+
options[:scope] = serialization_scope unless options.has_key?(:scope)
|
74
|
+
options[:resource_name] = controller_name if resource.respond_to?(:to_ary)
|
75
|
+
|
76
|
+
serializer.new(resource, options)
|
58
77
|
end
|
59
78
|
end
|
60
79
|
end
|
@@ -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,104 +1,65 @@
|
|
1
|
-
require
|
2
|
-
require '
|
3
|
-
require 'active_support/descendants_tracker'
|
1
|
+
require 'active_model/default_serializer'
|
2
|
+
require 'active_model/serializable'
|
4
3
|
|
5
4
|
module ActiveModel
|
6
|
-
# Active Model Array Serializer
|
7
|
-
#
|
8
|
-
# Serializes an Array, checking if each element implements
|
9
|
-
# the +active_model_serializer+ method.
|
10
|
-
#
|
11
|
-
# To disable serialization of root elements:
|
12
|
-
#
|
13
|
-
# ActiveModel::ArraySerializer.root = false
|
14
|
-
#
|
15
5
|
class ArraySerializer
|
16
|
-
|
17
|
-
|
18
|
-
attr_reader :object, :options
|
19
|
-
|
20
|
-
class_attribute :root
|
21
|
-
|
22
|
-
class_attribute :cache
|
23
|
-
class_attribute :perform_caching
|
6
|
+
include Serializable
|
24
7
|
|
25
8
|
class << self
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
9
|
+
attr_accessor :_root
|
10
|
+
alias root _root=
|
11
|
+
alias root= _root=
|
30
12
|
end
|
31
13
|
|
32
14
|
def initialize(object, options={})
|
33
|
-
@object
|
15
|
+
@object = object
|
16
|
+
@scope = options[:scope]
|
17
|
+
@root = options.fetch(:root, self.class._root)
|
18
|
+
@meta_key = options[:meta_key] || :meta
|
19
|
+
@meta = options[@meta_key]
|
20
|
+
@each_serializer = options[:each_serializer]
|
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)
|
34
25
|
end
|
26
|
+
attr_accessor :object, :scope, :root, :meta_key, :meta, :key_format
|
35
27
|
|
36
|
-
def
|
37
|
-
|
38
|
-
end
|
28
|
+
def json_key
|
29
|
+
key = root.nil? ? @resource_name : root
|
39
30
|
|
40
|
-
|
41
|
-
hash[meta_key] = @options[:meta] if @options.has_key?(:meta)
|
31
|
+
key_format == :lower_camel && key.present? ? key.camelize(:lower) : key
|
42
32
|
end
|
43
33
|
|
44
|
-
def
|
45
|
-
|
46
|
-
@
|
47
|
-
|
48
|
-
if root = @options[:root]
|
49
|
-
hash.merge!(root => serializable_array)
|
50
|
-
include_meta hash
|
51
|
-
hash
|
52
|
-
else
|
53
|
-
serializable_array
|
54
|
-
end
|
34
|
+
def serializer_for(item)
|
35
|
+
serializer_class = @each_serializer || Serializer.serializer_for(item) || DefaultSerializer
|
36
|
+
serializer_class.new(item, scope: scope, key_format: key_format, only: @only, except: @except)
|
55
37
|
end
|
56
38
|
|
57
|
-
def
|
58
|
-
|
59
|
-
|
60
|
-
super
|
61
|
-
end
|
62
|
-
else
|
63
|
-
super
|
39
|
+
def serializable_object
|
40
|
+
@object.map do |item|
|
41
|
+
serializer_for(item).serializable_object
|
64
42
|
end
|
65
43
|
end
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
44
|
+
alias_method :serializable_array, :serializable_object
|
45
|
+
|
46
|
+
def embedded_in_root_associations
|
47
|
+
@object.each_with_object({}) do |item, hash|
|
48
|
+
serializer_for(item).embedded_in_root_associations.each_pair do |type, objects|
|
49
|
+
next if !objects || objects.flatten.empty?
|
50
|
+
|
51
|
+
if hash.has_key?(type)
|
52
|
+
hash[type].concat(objects).uniq!
|
53
|
+
else
|
54
|
+
hash[type] = objects
|
55
|
+
end
|
71
56
|
end
|
72
|
-
else
|
73
|
-
_serializable_array
|
74
57
|
end
|
75
58
|
end
|
76
59
|
|
77
60
|
private
|
78
|
-
def
|
79
|
-
|
80
|
-
if @options.has_key? :each_serializer
|
81
|
-
serializer = @options[:each_serializer]
|
82
|
-
elsif item.respond_to?(:active_model_serializer)
|
83
|
-
serializer = item.active_model_serializer
|
84
|
-
end
|
85
|
-
|
86
|
-
serializable = serializer ? serializer.new(item, @options) : DefaultSerializer.new(item, @options.merge(:root => false))
|
87
|
-
|
88
|
-
if serializable.respond_to?(:serializable_hash)
|
89
|
-
serializable.serializable_hash
|
90
|
-
else
|
91
|
-
serializable.as_json
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
def expand_cache_key(*args)
|
97
|
-
ActiveSupport::Cache.expand_cache_key(args)
|
98
|
-
end
|
99
|
-
|
100
|
-
def perform_caching?
|
101
|
-
perform_caching && cache && respond_to?(:cache_key)
|
61
|
+
def instrumentation_keys
|
62
|
+
[:object, :scope, :root, :meta_key, :meta, :each_serializer, :resource_name, :key_format]
|
102
63
|
end
|
103
64
|
end
|
104
65
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'active_model/serializable'
|
2
|
+
|
3
|
+
module ActiveModel
|
4
|
+
# DefaultSerializer
|
5
|
+
#
|
6
|
+
# Provides a constant interface for all items
|
7
|
+
class DefaultSerializer
|
8
|
+
include ActiveModel::Serializable
|
9
|
+
|
10
|
+
attr_reader :object
|
11
|
+
|
12
|
+
def initialize(object, options={})
|
13
|
+
@object = object
|
14
|
+
@wrap_in_array = options[:_wrap_in_array]
|
15
|
+
end
|
16
|
+
|
17
|
+
def as_json(options={})
|
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
|
23
|
+
end
|
24
|
+
alias serializable_hash as_json
|
25
|
+
alias serializable_object as_json
|
26
|
+
|
27
|
+
private
|
28
|
+
def instrumentation_keys
|
29
|
+
[:object, :wrap_in_array]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module ActiveModel
|
2
|
+
module Serializable
|
3
|
+
def as_json(options={})
|
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
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def serializable_data
|
16
|
+
embedded_in_root_associations.tap do |hash|
|
17
|
+
if respond_to?(:meta) && meta
|
18
|
+
hash[meta_key] = meta
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def embedded_in_root_associations
|
24
|
+
{}
|
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
|
39
|
+
end
|
40
|
+
end
|
@@ -1,231 +1,100 @@
|
|
1
|
+
require 'active_model/default_serializer'
|
2
|
+
|
1
3
|
module ActiveModel
|
2
4
|
class Serializer
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
# this could fail if it needs a valid source, for example a polymorphic association
|
26
|
-
end
|
27
|
-
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
self.options = {}
|
32
|
-
|
33
|
-
def initialize(name, source, options={})
|
34
|
-
@name = name
|
35
|
-
@source = source
|
36
|
-
@options = options
|
37
|
-
end
|
38
|
-
|
39
|
-
def option(key, default=nil)
|
40
|
-
if @options.key?(key)
|
41
|
-
@options[key]
|
42
|
-
elsif self.class.options.key?(key)
|
43
|
-
self.class.options[key]
|
44
|
-
else
|
45
|
-
default
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def target_serializer
|
50
|
-
serializer = option(:serializer)
|
51
|
-
serializer.is_a?(String) ? serializer.constantize : serializer
|
52
|
-
end
|
53
|
-
|
54
|
-
def source_serializer
|
55
|
-
@source
|
56
|
-
end
|
57
|
-
|
58
|
-
def key
|
59
|
-
option(:key) || @name
|
60
|
-
end
|
61
|
-
|
62
|
-
def root
|
63
|
-
option(:root) || @name
|
64
|
-
end
|
65
|
-
|
66
|
-
def name
|
67
|
-
option(:name) || @name
|
68
|
-
end
|
69
|
-
|
70
|
-
def associated_object
|
71
|
-
option(:value) || source_serializer.send(name)
|
72
|
-
end
|
73
|
-
|
74
|
-
def embed_ids?
|
75
|
-
[:id, :ids].include? option(:embed, source_serializer._embed)
|
76
|
-
end
|
77
|
-
|
78
|
-
def embed_objects?
|
79
|
-
[:object, :objects].include? option(:embed, source_serializer._embed)
|
80
|
-
end
|
81
|
-
|
82
|
-
def embed_in_root?
|
83
|
-
option(:include, source_serializer._root_embed)
|
84
|
-
end
|
85
|
-
|
86
|
-
def embeddable?
|
87
|
-
!associated_object.nil?
|
88
|
-
end
|
5
|
+
class Association
|
6
|
+
def initialize(name, options={})
|
7
|
+
if options.has_key?(:include)
|
8
|
+
ActiveSupport::Deprecation.warn <<-WARN
|
9
|
+
** Notice: include was renamed to embed_in_root. **
|
10
|
+
WARN
|
11
|
+
end
|
12
|
+
|
13
|
+
@name = name.to_s
|
14
|
+
@options = options
|
15
|
+
self.embed = options.fetch(:embed) { CONFIG.embed }
|
16
|
+
@embed_in_root = options.fetch(:embed_in_root) { options.fetch(:include) { CONFIG.embed_in_root } }
|
17
|
+
@key_format = options.fetch(:key_format) { CONFIG.key_format }
|
18
|
+
@embed_key = options[:embed_key] || :id
|
19
|
+
@key = options[:key]
|
20
|
+
@embedded_key = options[:root] || name
|
21
|
+
@embed_in_root_key = options.fetch(:embed_in_root_key) { CONFIG.embed_in_root_key }
|
22
|
+
@embed_namespace = options.fetch(:embed_namespace) { CONFIG.embed_namespace }
|
23
|
+
|
24
|
+
serializer = @options[:serializer]
|
25
|
+
@serializer_from_options = serializer.is_a?(String) ? serializer.constantize : serializer
|
26
|
+
end
|
89
27
|
|
90
|
-
|
28
|
+
attr_reader :name, :embed_ids, :embed_objects
|
29
|
+
attr_accessor :embed_in_root, :embed_key, :key, :embedded_key, :root_key, :serializer_from_options, :options, :key_format, :embed_in_root_key, :embed_namespace
|
30
|
+
alias embed_ids? embed_ids
|
31
|
+
alias embed_objects? embed_objects
|
32
|
+
alias embed_in_root? embed_in_root
|
33
|
+
alias embed_in_root_key? embed_in_root_key
|
34
|
+
alias embed_namespace? embed_namespace
|
35
|
+
|
36
|
+
def embed=(embed)
|
37
|
+
@embed_ids = embed == :id || embed == :ids
|
38
|
+
@embed_objects = embed == :object || embed == :objects
|
39
|
+
end
|
91
40
|
|
92
|
-
|
93
|
-
|
94
|
-
target_serializer.new(object, source_serializer.options)
|
95
|
-
elsif object.respond_to?(:active_model_serializer) && (ams = object.active_model_serializer)
|
96
|
-
ams.new(object, source_serializer.options)
|
97
|
-
else
|
98
|
-
object
|
99
|
-
end
|
100
|
-
end
|
41
|
+
def serializer_from_object(object)
|
42
|
+
Serializer.serializer_for(object)
|
101
43
|
end
|
102
44
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
key
|
107
|
-
elsif embed_ids?
|
108
|
-
"#{@name.to_s.singularize}_ids".to_sym
|
109
|
-
else
|
110
|
-
@name
|
111
|
-
end
|
112
|
-
end
|
45
|
+
def default_serializer
|
46
|
+
DefaultSerializer
|
47
|
+
end
|
113
48
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
else
|
118
|
-
:id
|
119
|
-
end
|
120
|
-
end
|
49
|
+
def build_serializer(object, options = {})
|
50
|
+
serializer_class(object).new(object, options.merge(self.options))
|
51
|
+
end
|
121
52
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
53
|
+
class HasOne < Association
|
54
|
+
def initialize(name, *args)
|
55
|
+
super
|
56
|
+
@root_key = @embedded_key.to_s.pluralize
|
57
|
+
@key ||= "#{name}_id"
|
126
58
|
end
|
127
59
|
|
128
|
-
def
|
129
|
-
|
130
|
-
find_serializable(item)
|
131
|
-
end
|
60
|
+
def serializer_class(object)
|
61
|
+
serializer_from_options || serializer_from_object(object) || default_serializer
|
132
62
|
end
|
133
63
|
|
134
|
-
def
|
135
|
-
|
136
|
-
|
137
|
-
source_serializer.object.read_attribute_for_serialization(ids_key)
|
138
|
-
else
|
139
|
-
associated_object.map do |item|
|
140
|
-
item.read_attribute_for_serialization(embed_key)
|
141
|
-
end
|
142
|
-
end
|
64
|
+
def build_serializer(object, options = {})
|
65
|
+
options[:_wrap_in_array] = embed_in_root?
|
66
|
+
super
|
143
67
|
end
|
144
68
|
end
|
145
69
|
|
146
|
-
class
|
147
|
-
def
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
true
|
152
|
-
end
|
70
|
+
class HasMany < Association
|
71
|
+
def initialize(name, *args)
|
72
|
+
super
|
73
|
+
@root_key = @embedded_key
|
74
|
+
@key ||= "#{name.to_s.singularize}_ids"
|
153
75
|
end
|
154
76
|
|
155
|
-
def
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
def root
|
160
|
-
if root = option(:root)
|
161
|
-
root
|
162
|
-
elsif polymorphic?
|
163
|
-
associated_object.class.to_s.pluralize.demodulize.underscore.to_sym
|
77
|
+
def serializer_class(object)
|
78
|
+
if use_array_serializer?
|
79
|
+
ArraySerializer
|
164
80
|
else
|
165
|
-
|
81
|
+
serializer_from_options
|
166
82
|
end
|
167
83
|
end
|
168
84
|
|
169
|
-
def
|
170
|
-
if
|
171
|
-
|
172
|
-
elsif embed_ids? && !polymorphic?
|
173
|
-
"#{@name}_id".to_sym
|
85
|
+
def options
|
86
|
+
if use_array_serializer?
|
87
|
+
{ each_serializer: serializer_from_options }.merge! super
|
174
88
|
else
|
175
|
-
|
89
|
+
super
|
176
90
|
end
|
177
91
|
end
|
178
92
|
|
179
|
-
|
180
|
-
if key = option(:embed_key)
|
181
|
-
key
|
182
|
-
else
|
183
|
-
:id
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
def polymorphic_key
|
188
|
-
associated_object.class.to_s.demodulize.underscore.to_sym
|
189
|
-
end
|
93
|
+
private
|
190
94
|
|
191
|
-
def
|
192
|
-
|
193
|
-
|
194
|
-
if object && polymorphic?
|
195
|
-
{
|
196
|
-
:type => polymorphic_key,
|
197
|
-
polymorphic_key => find_serializable(object).serializable_hash
|
198
|
-
}
|
199
|
-
elsif object
|
200
|
-
find_serializable(object).serializable_hash
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
def serializables
|
205
|
-
object = associated_object
|
206
|
-
value = object && find_serializable(object)
|
207
|
-
value ? [value] : []
|
208
|
-
end
|
209
|
-
|
210
|
-
def serialize_ids
|
211
|
-
id_key = "#{@name}_id".to_sym
|
212
|
-
|
213
|
-
if polymorphic?
|
214
|
-
if associated_object
|
215
|
-
{
|
216
|
-
:type => polymorphic_key,
|
217
|
-
:id => associated_object.read_attribute_for_serialization(embed_key)
|
218
|
-
}
|
219
|
-
else
|
220
|
-
nil
|
221
|
-
end
|
222
|
-
elsif !option(:embed_key) && !source_serializer.respond_to?(@name.to_s) && source_serializer.object.respond_to?(id_key)
|
223
|
-
source_serializer.object.read_attribute_for_serialization(id_key)
|
224
|
-
elsif associated_object
|
225
|
-
associated_object.read_attribute_for_serialization(embed_key)
|
226
|
-
else
|
227
|
-
nil
|
228
|
-
end
|
95
|
+
def use_array_serializer?
|
96
|
+
!serializer_from_options ||
|
97
|
+
serializer_from_options && !(serializer_from_options <= ArraySerializer)
|
229
98
|
end
|
230
99
|
end
|
231
100
|
end
|