active_model_serializers 0.8.3 → 0.9.1
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 +31 -5
- data/CONTRIBUTING.md +20 -0
- data/DESIGN.textile +4 -4
- data/{MIT-LICENSE.txt → MIT-LICENSE} +0 -0
- data/README.md +395 -95
- data/lib/action_controller/serialization.rb +50 -12
- data/lib/action_controller/serialization_test_case.rb +79 -0
- data/lib/active_model/array_serializer.rb +46 -78
- data/lib/active_model/default_serializer.rb +32 -0
- data/lib/active_model/serializable/utils.rb +16 -0
- data/lib/active_model/serializable.rb +62 -0
- data/lib/active_model/serializer/association/has_many.rb +39 -0
- data/lib/active_model/serializer/association/has_one.rb +25 -0
- data/lib/active_model/serializer/association.rb +58 -0
- 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 +18 -0
- data/lib/active_model/{serializers → serializer}/version.rb +1 -1
- data/lib/active_model/serializer.rb +209 -422
- data/lib/active_model/serializer_support.rb +5 -0
- data/lib/active_model_serializers.rb +12 -87
- data/test/fixtures/active_record.rb +92 -0
- data/test/fixtures/poro.rb +184 -0
- data/test/fixtures/template.html.erb +1 -0
- data/test/integration/action_controller/namespaced_serialization_test.rb +96 -0
- data/test/integration/action_controller/serialization_test.rb +303 -0
- data/test/integration/action_controller/serialization_test_case_test.rb +71 -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 +14 -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 +36 -0
- data/test/unit/active_model/serializer/associations_test.rb +19 -0
- data/test/unit/active_model/serializer/attributes_test.rb +57 -0
- data/test/unit/active_model/serializer/config_test.rb +91 -0
- data/test/unit/active_model/serializer/filter_test.rb +69 -0
- data/test/unit/active_model/serializer/has_many_polymorphic_test.rb +189 -0
- data/test/unit/active_model/serializer/has_many_test.rb +265 -0
- data/test/unit/active_model/serializer/has_one_and_has_many_test.rb +27 -0
- data/test/unit/active_model/serializer/has_one_polymorphic_test.rb +196 -0
- data/test/unit/active_model/serializer/has_one_test.rb +239 -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 +34 -0
- data/test/unit/active_model/serializer/root_test.rb +117 -0
- data/test/unit/active_model/serializer/scope_test.rb +49 -0
- data/test/unit/active_model/serializer/url_helpers_test.rb +35 -0
- metadata +104 -63
- 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_model/serializer/associations.rb +0 -233
- 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,70 @@ 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
|
-
|
38
|
-
|
39
|
-
|
40
|
-
def default_serializer_options
|
42
|
+
module ClassMethods
|
43
|
+
def serialization_scope(scope)
|
44
|
+
self._serialization_scope = scope
|
45
|
+
end
|
41
46
|
end
|
42
47
|
|
43
48
|
[:_render_option_json, :_render_with_renderer_json].each do |renderer_method|
|
44
49
|
define_method renderer_method do |resource, options|
|
45
|
-
|
50
|
+
serializer = build_json_serializer(resource, options)
|
46
51
|
|
47
|
-
if
|
48
|
-
super(
|
52
|
+
if serializer
|
53
|
+
super(serializer, options)
|
49
54
|
else
|
50
55
|
super(resource, options)
|
51
56
|
end
|
52
57
|
end
|
53
58
|
end
|
54
59
|
|
55
|
-
|
56
|
-
|
57
|
-
|
60
|
+
private
|
61
|
+
|
62
|
+
def namespace_for_serializer
|
63
|
+
@namespace_for_serializer ||= self.class.parent unless self.class.parent == Object
|
64
|
+
end
|
65
|
+
|
66
|
+
def default_serializer(resource)
|
67
|
+
options = {}.tap do |o|
|
68
|
+
o[:namespace] = namespace_for_serializer if namespace_for_serializer
|
69
|
+
end
|
70
|
+
|
71
|
+
ActiveModel::Serializer.serializer_for(resource, options)
|
72
|
+
end
|
73
|
+
|
74
|
+
def default_serializer_options
|
75
|
+
{}
|
76
|
+
end
|
77
|
+
|
78
|
+
def serialization_scope
|
79
|
+
_serialization_scope = self.class._serialization_scope
|
80
|
+
send(_serialization_scope) if _serialization_scope && respond_to?(_serialization_scope, true)
|
81
|
+
end
|
82
|
+
|
83
|
+
def build_json_serializer(resource, options = {})
|
84
|
+
options = default_serializer_options.merge(options)
|
85
|
+
@namespace_for_serializer = options.fetch(:namespace, nil)
|
86
|
+
|
87
|
+
if serializer = options.fetch(:serializer, default_serializer(resource))
|
88
|
+
options[:scope] = serialization_scope unless options.has_key?(:scope)
|
89
|
+
|
90
|
+
if resource.respond_to?(:each)
|
91
|
+
options[:resource_name] = controller_name
|
92
|
+
options[:namespace] = namespace_for_serializer if namespace_for_serializer
|
93
|
+
end
|
94
|
+
|
95
|
+
serializer.new(resource, options)
|
58
96
|
end
|
59
97
|
end
|
60
98
|
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module ActionController
|
2
|
+
module SerializationAssertions
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
setup :setup_serialization_subscriptions
|
7
|
+
teardown :teardown_serialization_subscriptions
|
8
|
+
end
|
9
|
+
|
10
|
+
def setup_serialization_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_serialization_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,72 @@
|
|
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
|
+
@polymorphic = options.fetch(:polymorphic, false)
|
19
|
+
@meta_key = options[:meta_key] || :meta
|
20
|
+
@meta = options[@meta_key]
|
21
|
+
@each_serializer = options[:each_serializer]
|
22
|
+
@resource_name = options[:resource_name]
|
23
|
+
@only = options[:only] ? Array(options[:only]) : nil
|
24
|
+
@except = options[:except] ? Array(options[:except]) : nil
|
25
|
+
@namespace = options[:namespace]
|
26
|
+
@key_format = options[:key_format] || options[:each_serializer].try(:key_format)
|
34
27
|
end
|
28
|
+
attr_accessor :object, :scope, :root, :meta_key, :meta, :key_format
|
35
29
|
|
36
|
-
def
|
37
|
-
|
38
|
-
end
|
30
|
+
def json_key
|
31
|
+
key = root.nil? ? @resource_name : root
|
39
32
|
|
40
|
-
|
41
|
-
hash[meta_key] = @options[:meta] if @options.has_key?(:meta)
|
33
|
+
key_format == :lower_camel && key.present? ? key.camelize(:lower) : key
|
42
34
|
end
|
43
35
|
|
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
|
36
|
+
def serializer_for(item)
|
37
|
+
serializer_class = @each_serializer || Serializer.serializer_for(item, namespace: @namespace) || DefaultSerializer
|
38
|
+
serializer_class.new(item, scope: scope, key_format: key_format, only: @only, except: @except, polymorphic: @polymorphic, namespace: @namespace)
|
55
39
|
end
|
56
40
|
|
57
|
-
def
|
58
|
-
|
59
|
-
|
60
|
-
super
|
61
|
-
end
|
62
|
-
else
|
63
|
-
super
|
41
|
+
def serializable_object(options={})
|
42
|
+
@object.map do |item|
|
43
|
+
serializer_for(item).serializable_object_with_notification(options)
|
64
44
|
end
|
65
45
|
end
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
46
|
+
alias_method :serializable_array, :serializable_object
|
47
|
+
|
48
|
+
def embedded_in_root_associations
|
49
|
+
@object.each_with_object({}) do |item, hash|
|
50
|
+
serializer_for(item).embedded_in_root_associations.each_pair do |type, objects|
|
51
|
+
next if !objects || objects.flatten.empty?
|
52
|
+
|
53
|
+
if hash.has_key?(type)
|
54
|
+
case hash[type] when Hash
|
55
|
+
hash[type].deep_merge!(objects){ |key, old, new| (Array(old) + Array(new)).uniq }
|
56
|
+
else
|
57
|
+
hash[type].concat(objects).uniq!
|
58
|
+
end
|
59
|
+
else
|
60
|
+
hash[type] = objects
|
61
|
+
end
|
71
62
|
end
|
72
|
-
else
|
73
|
-
_serializable_array
|
74
63
|
end
|
75
64
|
end
|
76
65
|
|
77
66
|
private
|
78
|
-
def _serializable_array
|
79
|
-
@object.map do |item|
|
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
67
|
|
100
|
-
def
|
101
|
-
|
68
|
+
def instrumentation_keys
|
69
|
+
[:object, :scope, :root, :meta_key, :meta, :each_serializer, :resource_name, :key_format]
|
102
70
|
end
|
103
71
|
end
|
104
72
|
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,16 @@
|
|
1
|
+
module ActiveModel
|
2
|
+
module Serializable
|
3
|
+
module Utils
|
4
|
+
extend self
|
5
|
+
|
6
|
+
def _const_get(const)
|
7
|
+
begin
|
8
|
+
method = RUBY_VERSION >= '2.0' ? :const_get : :qualified_const_get
|
9
|
+
Object.send method, const
|
10
|
+
rescue NameError
|
11
|
+
const.safe_constantize
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'active_model/serializable/utils'
|
2
|
+
|
3
|
+
module ActiveModel
|
4
|
+
module Serializable
|
5
|
+
def self.included(base)
|
6
|
+
base.extend Utils
|
7
|
+
end
|
8
|
+
|
9
|
+
def as_json(options={})
|
10
|
+
instrument('!serialize') do
|
11
|
+
if root = options.fetch(:root, json_key)
|
12
|
+
hash = { root => serializable_object(options) }
|
13
|
+
hash.merge!(serializable_data)
|
14
|
+
hash
|
15
|
+
else
|
16
|
+
serializable_object(options)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def serializable_object_with_notification(options={})
|
22
|
+
instrument('!serialize') do
|
23
|
+
serializable_object(options)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def serializable_data
|
28
|
+
embedded_in_root_associations.tap do |hash|
|
29
|
+
if respond_to?(:meta) && meta
|
30
|
+
hash[meta_key] = meta
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def namespace
|
36
|
+
get_namespace && Utils._const_get(get_namespace)
|
37
|
+
end
|
38
|
+
|
39
|
+
def embedded_in_root_associations
|
40
|
+
{}
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def get_namespace
|
46
|
+
modules = self.class.name.split('::')
|
47
|
+
modules[0..-2].join('::') if modules.size > 1
|
48
|
+
end
|
49
|
+
|
50
|
+
def instrument(action, &block)
|
51
|
+
payload = instrumentation_keys.inject({ serializer: self.class.name }) do |payload, key|
|
52
|
+
payload[:payload] = self.instance_variable_get(:"@#{key}")
|
53
|
+
payload
|
54
|
+
end
|
55
|
+
ActiveSupport::Notifications.instrument("#{action}.active_model_serializers", payload, &block)
|
56
|
+
end
|
57
|
+
|
58
|
+
def instrumentation_keys
|
59
|
+
[:object, :scope, :root, :meta_key, :meta, :wrap_in_array, :only, :except, :key_format]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module ActiveModel
|
2
|
+
class Serializer
|
3
|
+
class Association
|
4
|
+
class HasMany < Association
|
5
|
+
def initialize(name, *args)
|
6
|
+
super
|
7
|
+
@root_key = @embedded_key.to_s
|
8
|
+
@key ||= case CONFIG.default_key_type
|
9
|
+
when :name then name.to_s.pluralize
|
10
|
+
else "#{name.to_s.singularize}_ids"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def serializer_class(object, _)
|
15
|
+
if use_array_serializer?
|
16
|
+
ArraySerializer
|
17
|
+
else
|
18
|
+
serializer_from_options
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def options
|
23
|
+
if use_array_serializer?
|
24
|
+
{ each_serializer: serializer_from_options }.merge! super
|
25
|
+
else
|
26
|
+
super
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def use_array_serializer?
|
33
|
+
!serializer_from_options ||
|
34
|
+
serializer_from_options && !(serializer_from_options <= ArraySerializer)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module ActiveModel
|
2
|
+
class Serializer
|
3
|
+
class Association
|
4
|
+
class HasOne < Association
|
5
|
+
def initialize(name, *args)
|
6
|
+
super
|
7
|
+
@root_key = @embedded_key.to_s.pluralize
|
8
|
+
@key ||= case CONFIG.default_key_type
|
9
|
+
when :name then name.to_s.singularize
|
10
|
+
else "#{name}_id"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def serializer_class(object, options = {})
|
15
|
+
serializer_from_options || serializer_from_object(object, options) || default_serializer
|
16
|
+
end
|
17
|
+
|
18
|
+
def build_serializer(object, options = {})
|
19
|
+
options[:_wrap_in_array] = embed_in_root?
|
20
|
+
super
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'active_model/default_serializer'
|
2
|
+
require 'active_model/serializer/association/has_one'
|
3
|
+
require 'active_model/serializer/association/has_many'
|
4
|
+
|
5
|
+
module ActiveModel
|
6
|
+
class Serializer
|
7
|
+
class Association
|
8
|
+
def initialize(name, options={})
|
9
|
+
if options.has_key?(:include)
|
10
|
+
ActiveSupport::Deprecation.warn <<-WARN
|
11
|
+
** Notice: include was renamed to embed_in_root. **
|
12
|
+
WARN
|
13
|
+
end
|
14
|
+
|
15
|
+
@name = name.to_s
|
16
|
+
@options = options
|
17
|
+
self.embed = options.fetch(:embed) { CONFIG.embed }
|
18
|
+
@polymorphic = options.fetch(:polymorphic, false)
|
19
|
+
@embed_in_root = options.fetch(:embed_in_root) { options.fetch(:include) { CONFIG.embed_in_root } }
|
20
|
+
@key_format = options.fetch(:key_format) { CONFIG.key_format }
|
21
|
+
@embed_key = options[:embed_key] || :id
|
22
|
+
@key = options[:key]
|
23
|
+
@embedded_key = options[:root] || name
|
24
|
+
@embed_in_root_key = options.fetch(:embed_in_root_key) { CONFIG.embed_in_root_key }
|
25
|
+
@embed_namespace = options.fetch(:embed_namespace) { CONFIG.embed_namespace }
|
26
|
+
|
27
|
+
serializer = @options[:serializer]
|
28
|
+
@serializer_from_options = serializer.is_a?(String) ? serializer.constantize : serializer
|
29
|
+
end
|
30
|
+
|
31
|
+
attr_reader :name, :embed_ids, :embed_objects, :polymorphic
|
32
|
+
attr_accessor :embed_in_root, :embed_key, :key, :embedded_key, :root_key, :serializer_from_options, :options, :key_format, :embed_in_root_key, :embed_namespace
|
33
|
+
alias embed_ids? embed_ids
|
34
|
+
alias embed_objects? embed_objects
|
35
|
+
alias embed_in_root? embed_in_root
|
36
|
+
alias embed_in_root_key? embed_in_root_key
|
37
|
+
alias embed_namespace? embed_namespace
|
38
|
+
alias polymorphic? polymorphic
|
39
|
+
|
40
|
+
def embed=(embed)
|
41
|
+
@embed_ids = embed == :id || embed == :ids
|
42
|
+
@embed_objects = embed == :object || embed == :objects
|
43
|
+
end
|
44
|
+
|
45
|
+
def serializer_from_object(object, options = {})
|
46
|
+
Serializer.serializer_for(object, options)
|
47
|
+
end
|
48
|
+
|
49
|
+
def default_serializer
|
50
|
+
DefaultSerializer
|
51
|
+
end
|
52
|
+
|
53
|
+
def build_serializer(object, options = {})
|
54
|
+
serializer_class(object, options).new(object, options.merge(self.options))
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module ActiveModel
|
2
|
+
class Serializer
|
3
|
+
class Config
|
4
|
+
def initialize(data = {})
|
5
|
+
@data = data
|
6
|
+
end
|
7
|
+
|
8
|
+
def each(&block)
|
9
|
+
@data.each(&block)
|
10
|
+
end
|
11
|
+
|
12
|
+
def clear
|
13
|
+
@data.clear
|
14
|
+
end
|
15
|
+
|
16
|
+
def method_missing(name, *args)
|
17
|
+
name = name.to_s
|
18
|
+
return @data[name] if @data.include?(name)
|
19
|
+
match = name.match(/\A(.*?)([?=]?)\Z/)
|
20
|
+
case match[2]
|
21
|
+
when "="
|
22
|
+
@data[match[1]] = args.first
|
23
|
+
when "?"
|
24
|
+
!!@data[match[1]]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
CONFIG = Config.new('embed' => :objects) # :nodoc:
|
30
|
+
end
|
31
|
+
end
|
File without changes
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
require 'rails/generators/rails/scaffold_controller/scaffold_controller_generator'
|
3
|
+
|
4
|
+
module Rails
|
5
|
+
module Generators
|
6
|
+
class ScaffoldControllerGenerator
|
7
|
+
if Rails::VERSION::MAJOR >= 4
|
8
|
+
source_root File.expand_path('../templates', __FILE__)
|
9
|
+
|
10
|
+
hook_for :serializer, default: true
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Rails
|
2
|
+
module Generators
|
3
|
+
class SerializerGenerator < NamedBase
|
4
|
+
source_root File.expand_path('../templates', __FILE__)
|
5
|
+
check_class_collision suffix: 'Serializer'
|
6
|
+
|
7
|
+
argument :attributes, type: :array, default: [], banner: 'field:type field:type'
|
8
|
+
|
9
|
+
class_option :parent, type: :string, desc: 'The parent class for the generated serializer'
|
10
|
+
|
11
|
+
def create_serializer_file
|
12
|
+
template 'serializer.rb', File.join('app/serializers', class_path, "#{file_name}_serializer.rb")
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def attributes_names
|
18
|
+
[:id] + attributes.select { |attr| !attr.reference? }.map { |a| a.name.to_sym }
|
19
|
+
end
|
20
|
+
|
21
|
+
def association_names
|
22
|
+
attributes.select { |attr| attr.reference? }.map { |a| a.name.to_sym }
|
23
|
+
end
|
24
|
+
|
25
|
+
def parent_class_name
|
26
|
+
if options[:parent]
|
27
|
+
options[:parent]
|
28
|
+
elsif (ns = Rails::Generators.namespace) && ns.const_defined?(:ApplicationSerializer) ||
|
29
|
+
(Object.const_get(:ApplicationSerializer) rescue nil)
|
30
|
+
'ApplicationSerializer'
|
31
|
+
else
|
32
|
+
'ActiveModel::Serializer'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|