active_model_serializers 0.9.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) 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 +110 -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.rb +16 -0
  20. data/test/integration/action_controller/serialization_test_case_test.rb +10 -0
  21. data/test/integration/active_record/active_record_test.rb +2 -2
  22. data/test/test_app.rb +3 -0
  23. data/test/tmp/app/serializers/account_serializer.rb +3 -0
  24. data/test/unit/active_model/array_serializer/serialization_test.rb +1 -1
  25. data/test/unit/active_model/serializer/associations/build_serializer_test.rb +15 -0
  26. data/test/unit/active_model/serializer/attributes_test.rb +16 -0
  27. data/test/unit/active_model/serializer/config_test.rb +3 -0
  28. data/test/unit/active_model/serializer/has_many_polymorphic_test.rb +189 -0
  29. data/test/unit/active_model/serializer/has_many_test.rb +51 -16
  30. data/test/unit/active_model/serializer/has_one_and_has_many_test.rb +27 -0
  31. data/test/unit/active_model/serializer/has_one_polymorphic_test.rb +196 -0
  32. data/test/unit/active_model/serializer/has_one_test.rb +32 -0
  33. data/test/unit/active_model/serializer/options_test.rb +19 -0
  34. data/test/unit/active_model/serializer/url_helpers_test.rb +35 -0
  35. metadata +40 -23
@@ -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.1'
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,28 @@ class ProfileSerializer < ActiveModel::Serializer
56
100
  attributes :name, :description
57
101
  end
58
102
 
103
+ class DifferentProfileSerializer < ActiveModel::Serializer
104
+ attributes :name
105
+ end
106
+
107
+ class CategorySerializer < ActiveModel::Serializer
108
+ attributes :name
109
+
110
+ has_many :posts
111
+ end
112
+
59
113
  class PostSerializer < ActiveModel::Serializer
60
114
  attributes :title, :body
61
115
 
62
116
  has_many :comments
63
117
  end
64
118
 
119
+ class SpecialPostSerializer < ActiveModel::Serializer
120
+ attributes :title, :body
121
+ has_many :comments, root: :comments, embed_in_root: true, embed: :ids
122
+ has_one :special_comment, root: :comments, embed_in_root: true, embed: :ids
123
+ end
124
+
65
125
  class CommentSerializer < ActiveModel::Serializer
66
126
  attributes :content
67
127
  end
@@ -73,3 +133,52 @@ end
73
133
  class WebLogLowerCamelSerializer < WebLogSerializer
74
134
  format_keys :lower_camel
75
135
  end
136
+
137
+ class InterviewSerializer < ActiveModel::Serializer
138
+ attributes :text
139
+
140
+ has_one :attachment, polymorphic: true
141
+ end
142
+
143
+ class MailSerializer < ActiveModel::Serializer
144
+ attributes :body
145
+
146
+ has_many :attachments, polymorphic: true
147
+ end
148
+
149
+ class ImageSerializer < ActiveModel::Serializer
150
+ attributes :url
151
+ end
152
+
153
+ class VideoSerializer < ActiveModel::Serializer
154
+ attributes :html
155
+ end
156
+
157
+ class ShortProfileSerializer < ::ProfileSerializer; end
158
+
159
+ module TestNamespace
160
+ class ProfileSerializer < ::ProfileSerializer; end
161
+ class UserSerializer < ::UserSerializer; end
162
+ end
163
+
164
+ ActiveModel::Serializer.setup do |config|
165
+ config.default_key_type = :name
166
+ end
167
+
168
+ class NameKeyUserSerializer < ActiveModel::Serializer
169
+ attributes :name, :email
170
+
171
+ has_one :profile
172
+ end
173
+
174
+ class NameKeyPostSerializer < ActiveModel::Serializer
175
+ attributes :title, :body
176
+
177
+ has_many :comments
178
+ end
179
+
180
+ ActiveModel::Serializer.setup do |config|
181
+ config.default_key_type = nil
182
+ end
183
+
184
+
@@ -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