active_model_serializers 0.10.4 → 0.10.5
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/.travis.yml +7 -3
- data/CHANGELOG.md +25 -1
- data/README.md +4 -4
- data/active_model_serializers.gemspec +1 -1
- data/appveyor.yml +9 -3
- data/docs/general/logging.md +7 -0
- data/docs/general/serializers.md +3 -3
- data/docs/howto/add_pagination_links.md +13 -13
- data/docs/howto/add_relationship_links.md +24 -21
- data/docs/howto/outside_controller_use.md +3 -2
- data/docs/howto/serialize_poro.md +46 -5
- data/docs/howto/upgrade_from_0_8_to_0_10.md +1 -1
- data/lib/active_model/serializer/version.rb +1 -1
- data/lib/active_model_serializers.rb +8 -0
- data/lib/active_model_serializers/model.rb +108 -30
- data/lib/active_model_serializers/test/schema.rb +2 -2
- data/lib/generators/rails/resource_override.rb +1 -1
- data/test/action_controller/adapter_selector_test.rb +11 -2
- data/test/action_controller/json_api/fields_test.rb +15 -6
- data/test/action_controller/json_api/transform_test.rb +11 -3
- data/test/action_controller/namespace_lookup_test.rb +14 -8
- data/test/action_controller/serialization_scope_name_test.rb +12 -6
- data/test/action_controller/serialization_test.rb +1 -1
- data/test/active_model_serializers/model_test.rb +122 -2
- data/test/active_model_serializers/railtie_test_isolated.rb +12 -7
- data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +37 -19
- data/test/adapter/attributes_test.rb +2 -5
- data/test/adapter/json/has_many_test.rb +10 -2
- data/test/adapter/json_api/fields_test.rb +11 -3
- data/test/adapter/json_api/has_many_test.rb +10 -2
- data/test/adapter/json_api/include_data_if_sideloaded_test.rb +22 -5
- data/test/adapter/json_api/linked_test.rb +3 -3
- data/test/adapter/json_api/links_test.rb +1 -1
- data/test/adapter/json_api/relationship_test.rb +1 -1
- data/test/adapter/json_api/transform_test.rb +11 -3
- data/test/cache_test.rb +100 -28
- data/test/collection_serializer_test.rb +23 -10
- data/test/fixtures/active_record.rb +45 -10
- data/test/fixtures/poro.rb +115 -176
- data/test/generators/serializer_generator_test.rb +1 -0
- data/test/grape_test.rb +20 -2
- data/test/serializers/associations_test.rb +28 -7
- data/test/serializers/attribute_test.rb +4 -2
- data/test/serializers/caching_configuration_test_isolated.rb +6 -6
- data/test/serializers/options_test.rb +17 -6
- data/test/serializers/read_attribute_for_serialization_test.rb +3 -3
- data/test/serializers/serialization_test.rb +2 -2
- data/test/serializers/serializer_for_test.rb +6 -6
- data/test/serializers/serializer_for_with_namespace_test.rb +6 -5
- data/test/support/rails_app.rb +2 -0
- data/test/test_helper.rb +12 -0
- metadata +13 -7
@@ -3,14 +3,27 @@ require 'test_helper'
|
|
3
3
|
module ActiveModel
|
4
4
|
class Serializer
|
5
5
|
class CollectionSerializerTest < ActiveSupport::TestCase
|
6
|
+
class SingularModel < ::Model; end
|
7
|
+
class SingularModelSerializer < ActiveModel::Serializer
|
8
|
+
end
|
9
|
+
class HasManyModel < ::Model
|
10
|
+
associations :singular_models
|
11
|
+
end
|
12
|
+
class HasManyModelSerializer < ActiveModel::Serializer
|
13
|
+
has_many :singular_models
|
14
|
+
|
15
|
+
def custom_options
|
16
|
+
instance_options
|
17
|
+
end
|
18
|
+
end
|
6
19
|
class MessagesSerializer < ActiveModel::Serializer
|
7
20
|
type 'messages'
|
8
21
|
end
|
9
22
|
|
10
23
|
def setup
|
11
|
-
@
|
12
|
-
@
|
13
|
-
@resource = build_named_collection @
|
24
|
+
@singular_model = SingularModel.new
|
25
|
+
@has_many_model = HasManyModel.new
|
26
|
+
@resource = build_named_collection @singular_model, @has_many_model
|
14
27
|
@serializer = collection_serializer.new(@resource, some: :options)
|
15
28
|
end
|
16
29
|
|
@@ -34,29 +47,29 @@ module ActiveModel
|
|
34
47
|
def test_each_object_should_be_serialized_with_appropriate_serializer
|
35
48
|
serializers = @serializer.to_a
|
36
49
|
|
37
|
-
assert_kind_of
|
38
|
-
assert_kind_of
|
50
|
+
assert_kind_of SingularModelSerializer, serializers.first
|
51
|
+
assert_kind_of SingularModel, serializers.first.object
|
39
52
|
|
40
|
-
assert_kind_of
|
41
|
-
assert_kind_of
|
53
|
+
assert_kind_of HasManyModelSerializer, serializers.last
|
54
|
+
assert_kind_of HasManyModel, serializers.last.object
|
42
55
|
|
43
56
|
assert_equal :options, serializers.last.custom_options[:some]
|
44
57
|
end
|
45
58
|
|
46
59
|
def test_serializer_option_not_passed_to_each_serializer
|
47
|
-
serializers = collection_serializer.new([@
|
60
|
+
serializers = collection_serializer.new([@has_many_model], serializer: HasManyModelSerializer).to_a
|
48
61
|
|
49
62
|
refute serializers.first.custom_options.key?(:serializer)
|
50
63
|
end
|
51
64
|
|
52
65
|
def test_root_default
|
53
|
-
@serializer = collection_serializer.new([@
|
66
|
+
@serializer = collection_serializer.new([@singular_model, @has_many_model])
|
54
67
|
assert_nil @serializer.root
|
55
68
|
end
|
56
69
|
|
57
70
|
def test_root
|
58
71
|
expected = 'custom_root'
|
59
|
-
@serializer = collection_serializer.new([@
|
72
|
+
@serializer = collection_serializer.new([@singular_model, @has_many_model], root: expected)
|
60
73
|
assert_equal expected, @serializer.root
|
61
74
|
end
|
62
75
|
|
@@ -47,16 +47,6 @@ module ARModels
|
|
47
47
|
has_many :comments
|
48
48
|
belongs_to :author
|
49
49
|
end
|
50
|
-
|
51
|
-
class Comment < ActiveRecord::Base
|
52
|
-
belongs_to :post
|
53
|
-
belongs_to :author
|
54
|
-
end
|
55
|
-
|
56
|
-
class Author < ActiveRecord::Base
|
57
|
-
has_many :posts
|
58
|
-
end
|
59
|
-
|
60
50
|
class PostSerializer < ActiveModel::Serializer
|
61
51
|
attributes :id, :title, :body
|
62
52
|
|
@@ -64,15 +54,60 @@ module ARModels
|
|
64
54
|
belongs_to :author
|
65
55
|
end
|
66
56
|
|
57
|
+
class Comment < ActiveRecord::Base
|
58
|
+
belongs_to :post
|
59
|
+
belongs_to :author
|
60
|
+
end
|
67
61
|
class CommentSerializer < ActiveModel::Serializer
|
68
62
|
attributes :id, :contents
|
69
63
|
|
70
64
|
belongs_to :author
|
71
65
|
end
|
72
66
|
|
67
|
+
class Author < ActiveRecord::Base
|
68
|
+
has_many :posts
|
69
|
+
end
|
73
70
|
class AuthorSerializer < ActiveModel::Serializer
|
74
71
|
attributes :id, :name
|
75
72
|
|
76
73
|
has_many :posts
|
77
74
|
end
|
78
75
|
end
|
76
|
+
|
77
|
+
class Employee < ActiveRecord::Base
|
78
|
+
has_many :pictures, as: :imageable
|
79
|
+
has_many :object_tags, as: :taggable
|
80
|
+
end
|
81
|
+
|
82
|
+
class PolymorphicSimpleSerializer < ActiveModel::Serializer
|
83
|
+
attributes :id
|
84
|
+
end
|
85
|
+
|
86
|
+
class ObjectTag < ActiveRecord::Base
|
87
|
+
belongs_to :poly_tag
|
88
|
+
belongs_to :taggable, polymorphic: true
|
89
|
+
end
|
90
|
+
class PolymorphicObjectTagSerializer < ActiveModel::Serializer
|
91
|
+
attributes :id
|
92
|
+
has_many :taggable, serializer: PolymorphicSimpleSerializer, polymorphic: true
|
93
|
+
end
|
94
|
+
|
95
|
+
class PolyTag < ActiveRecord::Base
|
96
|
+
has_many :object_tags
|
97
|
+
end
|
98
|
+
class PolymorphicTagSerializer < ActiveModel::Serializer
|
99
|
+
attributes :id, :phrase
|
100
|
+
has_many :object_tags, serializer: PolymorphicObjectTagSerializer
|
101
|
+
end
|
102
|
+
|
103
|
+
class Picture < ActiveRecord::Base
|
104
|
+
belongs_to :imageable, polymorphic: true
|
105
|
+
has_many :object_tags, as: :taggable
|
106
|
+
end
|
107
|
+
class PolymorphicHasManySerializer < ActiveModel::Serializer
|
108
|
+
attributes :id, :name
|
109
|
+
end
|
110
|
+
class PolymorphicBelongsToSerializer < ActiveModel::Serializer
|
111
|
+
attributes :id, :title
|
112
|
+
has_one :imageable, serializer: PolymorphicHasManySerializer, polymorphic: true
|
113
|
+
end
|
data/test/fixtures/poro.rb
CHANGED
@@ -1,25 +1,28 @@
|
|
1
|
-
verbose = $VERBOSE
|
2
|
-
$VERBOSE = nil
|
3
1
|
class Model < ActiveModelSerializers::Model
|
4
|
-
|
2
|
+
rand(2).zero? && derive_attributes_from_names_and_fix_accessors
|
5
3
|
|
6
|
-
|
4
|
+
attr_writer :id
|
7
5
|
|
8
|
-
#
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
6
|
+
# At this time, just for organization of intent
|
7
|
+
class_attribute :association_names
|
8
|
+
self.association_names = []
|
9
|
+
|
10
|
+
def self.associations(*names)
|
11
|
+
self.association_names |= names.map(&:to_sym)
|
12
|
+
# Silence redefinition of methods warnings
|
13
|
+
ActiveModelSerializers.silence_warnings do
|
14
|
+
attr_accessor(*names)
|
16
15
|
end
|
17
16
|
end
|
18
17
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
18
|
+
def associations
|
19
|
+
association_names.each_with_object({}) do |association_name, result|
|
20
|
+
result[association_name] = public_send(association_name).freeze
|
21
|
+
end.with_indifferent_access.freeze
|
22
|
+
end
|
23
|
+
|
24
|
+
def attributes
|
25
|
+
super.except(*association_names)
|
23
26
|
end
|
24
27
|
end
|
25
28
|
|
@@ -30,67 +33,59 @@ end
|
|
30
33
|
# model = ModelWithErrors.new
|
31
34
|
# model.validate! # => ["cannot be nil"]
|
32
35
|
# model.errors.full_messages # => ["name cannot be nil"]
|
33
|
-
class ModelWithErrors <
|
34
|
-
|
36
|
+
class ModelWithErrors < Model
|
37
|
+
attributes :name
|
35
38
|
end
|
36
39
|
|
37
40
|
class Profile < Model
|
41
|
+
attributes :name, :description
|
42
|
+
associations :comments
|
38
43
|
end
|
39
|
-
|
40
44
|
class ProfileSerializer < ActiveModel::Serializer
|
41
45
|
attributes :name, :description
|
42
|
-
|
43
|
-
# TODO: is this used anywhere?
|
44
|
-
def arguments_passed_in?
|
45
|
-
instance_options[:my_options] == :accessible
|
46
|
-
end
|
47
46
|
end
|
48
|
-
|
49
47
|
class ProfilePreviewSerializer < ActiveModel::Serializer
|
50
48
|
attributes :name
|
51
49
|
end
|
52
50
|
|
53
|
-
class
|
54
|
-
|
55
|
-
|
56
|
-
class Bio < Model; end
|
57
|
-
class Blog < Model; end
|
58
|
-
class Role < Model; end
|
59
|
-
class User < Model; end
|
60
|
-
class Location < Model; end
|
61
|
-
class Place < Model; end
|
62
|
-
class Tag < Model; end
|
63
|
-
class VirtualValue < Model; end
|
64
|
-
class Comment < Model
|
65
|
-
# Uses a custom non-time-based cache key
|
66
|
-
def cache_key
|
67
|
-
"#{self.class.name.downcase}/#{id}"
|
68
|
-
end
|
51
|
+
class Author < Model
|
52
|
+
attributes :name
|
53
|
+
associations :posts, :bio, :roles, :comments
|
69
54
|
end
|
55
|
+
class AuthorSerializer < ActiveModel::Serializer
|
56
|
+
cache key: 'writer', skip_digest: true
|
57
|
+
attribute :id
|
58
|
+
attribute :name
|
70
59
|
|
71
|
-
|
72
|
-
has_many :
|
73
|
-
|
60
|
+
has_many :posts
|
61
|
+
has_many :roles
|
62
|
+
has_one :bio
|
74
63
|
end
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
belongs_to :taggable, polymorphic: true
|
64
|
+
class AuthorPreviewSerializer < ActiveModel::Serializer
|
65
|
+
attributes :id
|
66
|
+
has_many :posts
|
79
67
|
end
|
80
68
|
|
81
|
-
class
|
82
|
-
|
83
|
-
|
69
|
+
class Comment < Model
|
70
|
+
attributes :body, :date
|
71
|
+
associations :post, :author, :likes
|
84
72
|
end
|
85
|
-
|
86
|
-
|
87
|
-
|
73
|
+
class CommentSerializer < ActiveModel::Serializer
|
74
|
+
cache expires_in: 1.day, skip_digest: true
|
75
|
+
attributes :id, :body
|
76
|
+
belongs_to :post
|
77
|
+
belongs_to :author
|
88
78
|
end
|
79
|
+
class CommentPreviewSerializer < ActiveModel::Serializer
|
80
|
+
attributes :id
|
89
81
|
|
90
|
-
|
91
|
-
class UnrelatedLink < Model; end
|
82
|
+
belongs_to :post
|
92
83
|
end
|
93
84
|
|
85
|
+
class Post < Model
|
86
|
+
attributes :title, :body
|
87
|
+
associations :author, :comments, :blog, :tags, :related
|
88
|
+
end
|
94
89
|
class PostSerializer < ActiveModel::Serializer
|
95
90
|
cache key: 'post', expires_in: 0.1, skip_digest: true
|
96
91
|
attributes :id, :title, :body
|
@@ -102,75 +97,28 @@ class PostSerializer < ActiveModel::Serializer
|
|
102
97
|
def blog
|
103
98
|
Blog.new(id: 999, name: 'Custom blog')
|
104
99
|
end
|
105
|
-
|
106
|
-
# TODO: is this used anywhere?
|
107
|
-
def custom_options
|
108
|
-
instance_options
|
109
|
-
end
|
110
100
|
end
|
111
|
-
|
112
101
|
class SpammyPostSerializer < ActiveModel::Serializer
|
113
102
|
attributes :id
|
114
103
|
has_many :related
|
115
104
|
end
|
105
|
+
class PostPreviewSerializer < ActiveModel::Serializer
|
106
|
+
attributes :title, :body, :id
|
116
107
|
|
117
|
-
|
118
|
-
|
119
|
-
attributes :id, :body
|
120
|
-
|
121
|
-
belongs_to :post
|
122
|
-
belongs_to :author
|
123
|
-
|
124
|
-
def custom_options
|
125
|
-
instance_options
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
class AuthorSerializer < ActiveModel::Serializer
|
130
|
-
cache key: 'writer', skip_digest: true
|
131
|
-
attribute :id
|
132
|
-
attribute :name
|
133
|
-
|
134
|
-
has_many :posts
|
135
|
-
has_many :roles
|
136
|
-
has_one :bio
|
137
|
-
end
|
138
|
-
|
139
|
-
class RoleSerializer < ActiveModel::Serializer
|
140
|
-
cache only: [:name, :slug], skip_digest: true
|
141
|
-
attributes :id, :name, :description
|
142
|
-
attribute :friendly_id, key: :slug
|
143
|
-
|
144
|
-
def friendly_id
|
145
|
-
"#{object.name}-#{object.id}"
|
146
|
-
end
|
147
|
-
|
148
|
-
belongs_to :author
|
149
|
-
end
|
150
|
-
|
151
|
-
class LikeSerializer < ActiveModel::Serializer
|
152
|
-
attributes :id, :time
|
153
|
-
|
154
|
-
belongs_to :likeable
|
108
|
+
has_many :comments, serializer: ::CommentPreviewSerializer
|
109
|
+
belongs_to :author, serializer: ::AuthorPreviewSerializer
|
155
110
|
end
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
belongs_to :place, key: :address
|
162
|
-
|
163
|
-
def place
|
164
|
-
'Nowhere'
|
165
|
-
end
|
111
|
+
class PostWithCustomKeysSerializer < ActiveModel::Serializer
|
112
|
+
attributes :id
|
113
|
+
has_many :comments, key: :reviews
|
114
|
+
belongs_to :author, key: :writer
|
115
|
+
has_one :blog, key: :site
|
166
116
|
end
|
167
117
|
|
168
|
-
class
|
169
|
-
attributes :
|
170
|
-
|
171
|
-
has_many :locations
|
118
|
+
class Bio < Model
|
119
|
+
attributes :content, :rating
|
120
|
+
associations :author
|
172
121
|
end
|
173
|
-
|
174
122
|
class BioSerializer < ActiveModel::Serializer
|
175
123
|
cache except: [:content], skip_digest: true
|
176
124
|
attributes :id, :content, :rating
|
@@ -178,6 +126,10 @@ class BioSerializer < ActiveModel::Serializer
|
|
178
126
|
belongs_to :author
|
179
127
|
end
|
180
128
|
|
129
|
+
class Blog < Model
|
130
|
+
attributes :name, :type, :special_attribute
|
131
|
+
associations :writer, :articles
|
132
|
+
end
|
181
133
|
class BlogSerializer < ActiveModel::Serializer
|
182
134
|
cache key: 'blog'
|
183
135
|
attributes :id, :name
|
@@ -185,61 +137,76 @@ class BlogSerializer < ActiveModel::Serializer
|
|
185
137
|
belongs_to :writer
|
186
138
|
has_many :articles
|
187
139
|
end
|
188
|
-
|
189
|
-
class PaginatedSerializer < ActiveModel::Serializer::CollectionSerializer
|
190
|
-
def json_key
|
191
|
-
'paginated'
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
140
|
class AlternateBlogSerializer < ActiveModel::Serializer
|
196
141
|
attribute :id
|
197
142
|
attribute :name, key: :title
|
198
143
|
end
|
199
|
-
|
200
144
|
class CustomBlogSerializer < ActiveModel::Serializer
|
201
145
|
attribute :id
|
202
146
|
attribute :special_attribute
|
203
|
-
|
204
147
|
has_many :articles
|
205
148
|
end
|
206
149
|
|
207
|
-
class
|
208
|
-
attributes :
|
209
|
-
|
210
|
-
belongs_to :post
|
150
|
+
class Role < Model
|
151
|
+
attributes :name, :description, :special_attribute
|
152
|
+
associations :author
|
211
153
|
end
|
154
|
+
class RoleSerializer < ActiveModel::Serializer
|
155
|
+
cache only: [:name, :slug], skip_digest: true
|
156
|
+
attributes :id, :name, :description
|
157
|
+
attribute :friendly_id, key: :slug
|
158
|
+
belongs_to :author
|
212
159
|
|
213
|
-
|
214
|
-
|
160
|
+
def friendly_id
|
161
|
+
"#{object.name}-#{object.id}"
|
162
|
+
end
|
163
|
+
end
|
215
164
|
|
216
|
-
|
165
|
+
class Location < Model
|
166
|
+
attributes :lat, :lng
|
167
|
+
associations :place
|
217
168
|
end
|
169
|
+
class LocationSerializer < ActiveModel::Serializer
|
170
|
+
cache only: [:address], skip_digest: true
|
171
|
+
attributes :id, :lat, :lng
|
218
172
|
|
219
|
-
|
220
|
-
attributes :title, :body, :id
|
173
|
+
belongs_to :place, key: :address
|
221
174
|
|
222
|
-
|
223
|
-
|
175
|
+
def place
|
176
|
+
'Nowhere'
|
177
|
+
end
|
224
178
|
end
|
225
179
|
|
226
|
-
class
|
227
|
-
attributes :
|
228
|
-
|
229
|
-
|
180
|
+
class Place < Model
|
181
|
+
attributes :name
|
182
|
+
associations :locations
|
183
|
+
end
|
184
|
+
class PlaceSerializer < ActiveModel::Serializer
|
185
|
+
attributes :id, :name
|
186
|
+
has_many :locations
|
230
187
|
end
|
231
188
|
|
232
|
-
class
|
233
|
-
attributes :
|
189
|
+
class Like < Model
|
190
|
+
attributes :time
|
191
|
+
associations :likeable
|
192
|
+
end
|
193
|
+
class LikeSerializer < ActiveModel::Serializer
|
194
|
+
attributes :id, :time
|
195
|
+
belongs_to :likeable
|
196
|
+
end
|
234
197
|
|
235
|
-
|
236
|
-
|
237
|
-
|
198
|
+
module Spam
|
199
|
+
class UnrelatedLink < Model
|
200
|
+
end
|
201
|
+
class UnrelatedLinkSerializer < ActiveModel::Serializer
|
202
|
+
cache only: [:id]
|
203
|
+
attributes :id
|
204
|
+
end
|
238
205
|
end
|
239
206
|
|
207
|
+
class VirtualValue < Model; end
|
240
208
|
class VirtualValueSerializer < ActiveModel::Serializer
|
241
209
|
attributes :id
|
242
|
-
|
243
210
|
has_many :reviews, virtual_value: [{ type: 'reviews', id: '1' },
|
244
211
|
{ type: 'reviews', id: '2' }]
|
245
212
|
has_one :maker, virtual_value: { type: 'makers', id: '1' }
|
@@ -251,36 +218,8 @@ class VirtualValueSerializer < ActiveModel::Serializer
|
|
251
218
|
end
|
252
219
|
end
|
253
220
|
|
254
|
-
class
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
class PolymorphicBelongsToSerializer < ActiveModel::Serializer
|
259
|
-
attributes :id, :title
|
260
|
-
|
261
|
-
has_one :imageable, serializer: PolymorphicHasManySerializer, polymorphic: true
|
262
|
-
end
|
263
|
-
|
264
|
-
class PolymorphicSimpleSerializer < ActiveModel::Serializer
|
265
|
-
attributes :id
|
266
|
-
end
|
267
|
-
|
268
|
-
class PolymorphicObjectTagSerializer < ActiveModel::Serializer
|
269
|
-
attributes :id
|
270
|
-
|
271
|
-
has_many :taggable, serializer: PolymorphicSimpleSerializer, polymorphic: true
|
272
|
-
end
|
273
|
-
|
274
|
-
class PolymorphicTagSerializer < ActiveModel::Serializer
|
275
|
-
attributes :id, :phrase
|
276
|
-
|
277
|
-
has_many :object_tags, serializer: PolymorphicObjectTagSerializer
|
278
|
-
end
|
279
|
-
|
280
|
-
module Spam
|
281
|
-
class UnrelatedLinkSerializer < ActiveModel::Serializer
|
282
|
-
cache only: [:id]
|
283
|
-
attributes :id
|
221
|
+
class PaginatedSerializer < ActiveModel::Serializer::CollectionSerializer
|
222
|
+
def json_key
|
223
|
+
'paginated'
|
284
224
|
end
|
285
225
|
end
|
286
|
-
$VERBOSE = verbose
|