active_model_serializers 0.9.0 → 0.9.3

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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -0
  3. data/README.md +109 -17
  4. data/lib/action_controller/serialization.rb +27 -8
  5. data/lib/action_controller/serialization_test_case.rb +4 -4
  6. data/lib/active_model/array_serializer.rb +12 -5
  7. data/lib/active_model/serializable.rb +24 -2
  8. data/lib/active_model/serializable/utils.rb +16 -0
  9. data/lib/active_model/serializer.rb +70 -36
  10. data/lib/active_model/serializer/{associations.rb → association.rb} +8 -52
  11. data/lib/active_model/serializer/association/has_many.rb +39 -0
  12. data/lib/active_model/serializer/association/has_one.rb +25 -0
  13. data/lib/active_model/serializer/railtie.rb +8 -0
  14. data/lib/active_model/serializer/version.rb +1 -1
  15. data/lib/active_model_serializers.rb +1 -1
  16. data/test/fixtures/poro.rb +106 -1
  17. data/test/fixtures/template.html.erb +1 -0
  18. data/test/integration/action_controller/namespaced_serialization_test.rb +96 -0
  19. data/test/integration/action_controller/serialization_test_case_test.rb +10 -0
  20. data/test/integration/active_record/active_record_test.rb +2 -2
  21. data/test/serializers/tmp/app/serializers/account_serializer.rb +3 -0
  22. data/test/test_app.rb +3 -0
  23. data/test/unit/active_model/array_serializer/serialization_test.rb +1 -1
  24. data/test/unit/active_model/serializer/associations/build_serializer_test.rb +15 -0
  25. data/test/unit/active_model/serializer/attributes_test.rb +16 -0
  26. data/test/unit/active_model/serializer/config_test.rb +3 -0
  27. data/test/unit/active_model/serializer/has_many_polymorphic_test.rb +189 -0
  28. data/test/unit/active_model/serializer/has_many_test.rb +51 -16
  29. data/test/unit/active_model/serializer/has_one_and_has_many_test.rb +27 -0
  30. data/test/unit/active_model/serializer/has_one_polymorphic_test.rb +196 -0
  31. data/test/unit/active_model/serializer/has_one_test.rb +32 -0
  32. data/test/unit/active_model/serializer/options_test.rb +19 -0
  33. data/test/unit/active_model/serializer/url_helpers_test.rb +35 -0
  34. metadata +44 -27
@@ -1,4 +1,6 @@
1
1
  require 'active_model/default_serializer'
2
+ require 'active_model/serializer/association/has_one'
3
+ require 'active_model/serializer/association/has_many'
2
4
 
3
5
  module ActiveModel
4
6
  class Serializer
@@ -13,6 +15,7 @@ module ActiveModel
13
15
  @name = name.to_s
14
16
  @options = options
15
17
  self.embed = options.fetch(:embed) { CONFIG.embed }
18
+ @polymorphic = options.fetch(:polymorphic, false)
16
19
  @embed_in_root = options.fetch(:embed_in_root) { options.fetch(:include) { CONFIG.embed_in_root } }
17
20
  @key_format = options.fetch(:key_format) { CONFIG.key_format }
18
21
  @embed_key = options[:embed_key] || :id
@@ -25,21 +28,22 @@ module ActiveModel
25
28
  @serializer_from_options = serializer.is_a?(String) ? serializer.constantize : serializer
26
29
  end
27
30
 
28
- attr_reader :name, :embed_ids, :embed_objects
31
+ attr_reader :name, :embed_ids, :embed_objects, :polymorphic
29
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
30
33
  alias embed_ids? embed_ids
31
34
  alias embed_objects? embed_objects
32
35
  alias embed_in_root? embed_in_root
33
36
  alias embed_in_root_key? embed_in_root_key
34
37
  alias embed_namespace? embed_namespace
38
+ alias polymorphic? polymorphic
35
39
 
36
40
  def embed=(embed)
37
41
  @embed_ids = embed == :id || embed == :ids
38
42
  @embed_objects = embed == :object || embed == :objects
39
43
  end
40
44
 
41
- def serializer_from_object(object)
42
- Serializer.serializer_for(object)
45
+ def serializer_from_object(object, options = {})
46
+ Serializer.serializer_for(object, options)
43
47
  end
44
48
 
45
49
  def default_serializer
@@ -47,55 +51,7 @@ module ActiveModel
47
51
  end
48
52
 
49
53
  def build_serializer(object, options = {})
50
- serializer_class(object).new(object, options.merge(self.options))
51
- end
52
-
53
- class HasOne < Association
54
- def initialize(name, *args)
55
- super
56
- @root_key = @embedded_key.to_s.pluralize
57
- @key ||= "#{name}_id"
58
- end
59
-
60
- def serializer_class(object)
61
- serializer_from_options || serializer_from_object(object) || default_serializer
62
- end
63
-
64
- def build_serializer(object, options = {})
65
- options[:_wrap_in_array] = embed_in_root?
66
- super
67
- end
68
- end
69
-
70
- class HasMany < Association
71
- def initialize(name, *args)
72
- super
73
- @root_key = @embedded_key
74
- @key ||= "#{name.to_s.singularize}_ids"
75
- end
76
-
77
- def serializer_class(object)
78
- if use_array_serializer?
79
- ArraySerializer
80
- else
81
- serializer_from_options
82
- end
83
- end
84
-
85
- def options
86
- if use_array_serializer?
87
- { each_serializer: serializer_from_options }.merge! super
88
- else
89
- super
90
- end
91
- end
92
-
93
- private
94
-
95
- def use_array_serializer?
96
- !serializer_from_options ||
97
- serializer_from_options && !(serializer_from_options <= ArraySerializer)
98
- end
54
+ serializer_class(object, options).new(object, options.merge(self.options))
99
55
  end
100
56
  end
101
57
  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
@@ -6,5 +6,13 @@ module ActiveModel
6
6
  require 'active_model/serializer/generators/serializer/scaffold_controller_generator'
7
7
  require 'active_model/serializer/generators/resource_override'
8
8
  end
9
+
10
+ initializer 'include_routes.active_model_serializer' do |app|
11
+ ActiveSupport.on_load(:active_model_serializers) do
12
+ include app.routes.url_helpers
13
+ end
14
+ end
9
15
  end
10
16
  end
17
+
18
+ ActiveSupport.run_load_hooks(:active_model_serializers, ActiveModel::Serializer)
@@ -1,5 +1,5 @@
1
1
  module ActiveModel
2
2
  class Serializer
3
- VERSION = '0.9.0'
3
+ VERSION = '0.9.3'
4
4
  end
5
5
  end
@@ -9,7 +9,7 @@ begin
9
9
  require 'action_controller/serialization'
10
10
  require 'action_controller/serialization_test_case'
11
11
 
12
- ActiveSupport.on_load(:after_initialize) do
12
+ ActiveSupport.on_load(:action_controller) do
13
13
  if ::ActionController::Serialization.enabled
14
14
  ActionController::Base.send(:include, ::ActionController::Serialization)
15
15
  ActionController::TestCase.send(:include, ::ActionController::SerializationAssertions)
@@ -1,11 +1,13 @@
1
1
  class Model
2
- def initialize(hash={})
2
+ def initialize(hash = {})
3
3
  @attributes = hash
4
4
  end
5
5
 
6
6
  def read_attribute_for_serialization(name)
7
7
  if name == :id || name == 'id'
8
8
  object_id
9
+ elsif respond_to?(name)
10
+ send name
9
11
  else
10
12
  @attributes[name]
11
13
  end
@@ -22,9 +24,22 @@ class User < Model
22
24
  end
23
25
  end
24
26
 
27
+ class UserInfo < Model
28
+ def user
29
+ @user ||= User.new(name: 'N1', email: 'E1')
30
+ end
31
+ end
32
+
25
33
  class Profile < Model
26
34
  end
27
35
 
36
+ class Category < Model
37
+ def posts
38
+ @posts ||= [Post.new(title: 'T1', body: 'B1'),
39
+ Post.new(title: 'T2', body: 'B2')]
40
+ end
41
+ end
42
+
28
43
  class Post < Model
29
44
  def comments
30
45
  @comments ||= [Comment.new(content: 'C1'),
@@ -32,12 +47,37 @@ class Post < Model
32
47
  end
33
48
  end
34
49
 
50
+ class SpecialPost < Post
51
+ def special_comment
52
+ @speical_comment ||= Comment.new(content: 'special')
53
+ end
54
+ end
55
+
35
56
  class Comment < Model
36
57
  end
37
58
 
38
59
  class WebLog < Model
39
60
  end
40
61
 
62
+ class Interview < Model
63
+ def attachment
64
+ @attachment ||= Image.new(url: 'U1')
65
+ end
66
+ end
67
+
68
+ class Mail < Model
69
+ def attachments
70
+ @attachments ||= [Image.new(url: 'U1'),
71
+ Video.new(html: 'H1')]
72
+ end
73
+ end
74
+
75
+ class Image < Model
76
+ end
77
+
78
+ class Video < Model
79
+ end
80
+
41
81
  ###
42
82
  ## Serializers
43
83
  ###
@@ -47,6 +87,10 @@ class UserSerializer < ActiveModel::Serializer
47
87
  has_one :profile
48
88
  end
49
89
 
90
+ class UserInfoSerializer < ActiveModel::Serializer
91
+ has_one :user
92
+ end
93
+
50
94
  class ProfileSerializer < ActiveModel::Serializer
51
95
  def description
52
96
  description = object.read_attribute_for_serialization(:description)
@@ -56,12 +100,24 @@ class ProfileSerializer < ActiveModel::Serializer
56
100
  attributes :name, :description
57
101
  end
58
102
 
103
+ class CategorySerializer < ActiveModel::Serializer
104
+ attributes :name
105
+
106
+ has_many :posts
107
+ end
108
+
59
109
  class PostSerializer < ActiveModel::Serializer
60
110
  attributes :title, :body
61
111
 
62
112
  has_many :comments
63
113
  end
64
114
 
115
+ class SpecialPostSerializer < ActiveModel::Serializer
116
+ attributes :title, :body
117
+ has_many :comments, root: :comments, embed_in_root: true, embed: :ids
118
+ has_one :special_comment, root: :comments, embed_in_root: true, embed: :ids
119
+ end
120
+
65
121
  class CommentSerializer < ActiveModel::Serializer
66
122
  attributes :content
67
123
  end
@@ -73,3 +129,52 @@ end
73
129
  class WebLogLowerCamelSerializer < WebLogSerializer
74
130
  format_keys :lower_camel
75
131
  end
132
+
133
+ class InterviewSerializer < ActiveModel::Serializer
134
+ attributes :text
135
+
136
+ has_one :attachment, polymorphic: true
137
+ end
138
+
139
+ class MailSerializer < ActiveModel::Serializer
140
+ attributes :body
141
+
142
+ has_many :attachments, polymorphic: true
143
+ end
144
+
145
+ class ImageSerializer < ActiveModel::Serializer
146
+ attributes :url
147
+ end
148
+
149
+ class VideoSerializer < ActiveModel::Serializer
150
+ attributes :html
151
+ end
152
+
153
+ class ShortProfileSerializer < ::ProfileSerializer; end
154
+
155
+ module TestNamespace
156
+ class ProfileSerializer < ::ProfileSerializer; end
157
+ class UserSerializer < ::UserSerializer; end
158
+ end
159
+
160
+ ActiveModel::Serializer.setup do |config|
161
+ config.default_key_type = :name
162
+ end
163
+
164
+ class NameKeyUserSerializer < ActiveModel::Serializer
165
+ attributes :name, :email
166
+
167
+ has_one :profile
168
+ end
169
+
170
+ class NameKeyPostSerializer < ActiveModel::Serializer
171
+ attributes :title, :body
172
+
173
+ has_many :comments
174
+ end
175
+
176
+ ActiveModel::Serializer.setup do |config|
177
+ config.default_key_type = nil
178
+ end
179
+
180
+
@@ -0,0 +1 @@
1
+ <p>Hello.</p>
@@ -0,0 +1,96 @@
1
+ require 'test_helper'
2
+
3
+ module ActionController
4
+ module Serialization
5
+ class NamespacedSerializationTest < ActionController::TestCase
6
+ class TestNamespace::MyController < ActionController::Base
7
+ def render_profile_with_namespace
8
+ render json: Profile.new({ name: 'Name 1', description: 'Description 1'})
9
+ end
10
+
11
+ def render_profiles_with_namespace
12
+ render json: [Profile.new({ name: 'Name 1', description: 'Description 1'})]
13
+ end
14
+
15
+ def render_comment
16
+ render json: Comment.new(content: 'Comment 1')
17
+ end
18
+
19
+ def render_comments
20
+ render json: [Comment.new(content: 'Comment 1')]
21
+ end
22
+ end
23
+
24
+ tests TestNamespace::MyController
25
+
26
+ def test_render_profile_with_namespace
27
+ get :render_profile_with_namespace
28
+ assert_serializer TestNamespace::ProfileSerializer
29
+ end
30
+
31
+ def test_render_profiles_with_namespace
32
+ get :render_profiles_with_namespace
33
+ assert_serializer TestNamespace::ProfileSerializer
34
+ end
35
+
36
+ def test_fallback_to_a_version_without_namespace
37
+ get :render_comment
38
+ assert_serializer CommentSerializer
39
+ end
40
+
41
+ def test_array_fallback_to_a_version_without_namespace
42
+ get :render_comments
43
+ assert_serializer CommentSerializer
44
+ end
45
+ end
46
+
47
+ class OptionNamespacedSerializationTest < ActionController::TestCase
48
+ class MyController < ActionController::Base
49
+ def default_serializer_options
50
+ {
51
+ namespace: TestNamespace
52
+ }
53
+ end
54
+
55
+ def render_profile_with_namespace_option
56
+ render json: Profile.new({ name: 'Name 1', description: 'Description 1'})
57
+ end
58
+
59
+ def render_profiles_with_namespace_option
60
+ render json: [Profile.new({ name: 'Name 1', description: 'Description 1'})]
61
+ end
62
+
63
+ def render_comment
64
+ render json: Comment.new(content: 'Comment 1')
65
+ end
66
+
67
+ def render_comments
68
+ render json: [Comment.new(content: 'Comment 1')]
69
+ end
70
+ end
71
+
72
+ tests MyController
73
+
74
+ def test_render_profile_with_namespace_option
75
+ get :render_profile_with_namespace_option
76
+ assert_serializer TestNamespace::ProfileSerializer
77
+ end
78
+
79
+ def test_render_profiles_with_namespace_option
80
+ get :render_profiles_with_namespace_option
81
+ assert_serializer TestNamespace::ProfileSerializer
82
+ end
83
+
84
+ def test_fallback_to_a_version_without_namespace
85
+ get :render_comment
86
+ assert_serializer CommentSerializer
87
+ end
88
+
89
+ def test_array_fallback_to_a_version_without_namespace
90
+ get :render_comments
91
+ assert_serializer CommentSerializer
92
+ end
93
+ end
94
+
95
+ end
96
+ end