active_model_serializers 0.7.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +3 -3
- data/CHANGELOG.md +61 -0
- data/DESIGN.textile +2 -2
- data/Gemfile +3 -1
- data/README.md +44 -21
- data/Rakefile +5 -0
- data/active_model_serializers.gemspec +2 -1
- data/bench/perf.rb +43 -0
- data/lib/action_controller/serialization.rb +8 -25
- data/lib/active_model/array_serializer.rb +58 -20
- data/lib/active_model/serializer.rb +132 -16
- data/lib/active_model/serializer/associations.rb +17 -10
- data/lib/active_model/serializers/version.rb +1 -1
- data/lib/active_model_serializers.rb +20 -8
- data/lib/active_record/serializer_override.rb +16 -0
- data/lib/generators/serializer/serializer_generator.rb +3 -2
- data/lib/generators/serializer/templates/serializer.rb +11 -0
- data/test/array_serializer_test.rb +0 -1
- data/test/association_test.rb +103 -0
- data/test/caching_test.rb +96 -0
- data/test/generators_test.rb +16 -2
- data/test/no_serialization_scope_test.rb +1 -1
- data/test/serialization_scope_name_test.rb +67 -0
- data/test/serialization_test.rb +1 -1
- data/test/serializer_support_test.rb +10 -0
- data/test/serializer_test.rb +142 -3
- data/test/test_fakes.rb +12 -0
- data/test/test_helper.rb +8 -7
- metadata +25 -4
- data/RELEASE_NOTES.md +0 -15
@@ -0,0 +1,96 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class CachingTest < ActiveModel::TestCase
|
4
|
+
class NullStore
|
5
|
+
def fetch(key)
|
6
|
+
return store[key] if store[key]
|
7
|
+
|
8
|
+
store[key] = yield
|
9
|
+
end
|
10
|
+
|
11
|
+
def clear
|
12
|
+
store.clear
|
13
|
+
end
|
14
|
+
|
15
|
+
def store
|
16
|
+
@store ||= {}
|
17
|
+
end
|
18
|
+
|
19
|
+
def read(key)
|
20
|
+
store[key]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Programmer
|
25
|
+
def name
|
26
|
+
'Adam'
|
27
|
+
end
|
28
|
+
|
29
|
+
def skills
|
30
|
+
%w(ruby)
|
31
|
+
end
|
32
|
+
|
33
|
+
def read_attribute_for_serialization(name)
|
34
|
+
send name
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_serializers_have_a_cache_store
|
39
|
+
ActiveModel::Serializer.cache = NullStore.new
|
40
|
+
|
41
|
+
assert_kind_of NullStore, ActiveModel::Serializer.cache
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_serializers_can_enable_caching
|
45
|
+
serializer = Class.new(ActiveModel::Serializer) do
|
46
|
+
cached true
|
47
|
+
end
|
48
|
+
|
49
|
+
assert serializer.perform_caching
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_serializers_use_cache
|
53
|
+
serializer = Class.new(ActiveModel::Serializer) do
|
54
|
+
cached true
|
55
|
+
attributes :name, :skills
|
56
|
+
|
57
|
+
def self.to_s
|
58
|
+
'serializer'
|
59
|
+
end
|
60
|
+
|
61
|
+
def cache_key
|
62
|
+
object.name
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
serializer.cache = NullStore.new
|
67
|
+
instance = serializer.new Programmer.new
|
68
|
+
|
69
|
+
instance.to_json
|
70
|
+
|
71
|
+
assert_equal(instance.serializable_hash, serializer.cache.read('serializer/Adam/serializable-hash'))
|
72
|
+
assert_equal(instance.to_json, serializer.cache.read('serializer/Adam/to-json'))
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_array_serializer_uses_cache
|
76
|
+
serializer = Class.new(ActiveModel::ArraySerializer) do
|
77
|
+
cached true
|
78
|
+
|
79
|
+
def self.to_s
|
80
|
+
'array_serializer'
|
81
|
+
end
|
82
|
+
|
83
|
+
def cache_key
|
84
|
+
'cache-key'
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
serializer.cache = NullStore.new
|
89
|
+
instance = serializer.new [Programmer.new]
|
90
|
+
|
91
|
+
instance.to_json
|
92
|
+
|
93
|
+
assert_equal instance.serializable_array, serializer.cache.read('array_serializer/cache-key/serializable-array')
|
94
|
+
assert_equal instance.to_json, serializer.cache.read('array_serializer/cache-key/to-json')
|
95
|
+
end
|
96
|
+
end
|
data/test/generators_test.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
class Foo < Rails::Application
|
4
|
-
if Rails.version.start_with? '4'
|
4
|
+
if Rails.version.to_s.start_with? '4'
|
5
5
|
config.eager_load = false
|
6
6
|
config.secret_key_base = 'abc123'
|
7
7
|
end
|
@@ -36,6 +36,18 @@ class SerializerGeneratorTest < Rails::Generators::TestCase
|
|
36
36
|
Object.send :remove_const, :ApplicationSerializer
|
37
37
|
end
|
38
38
|
|
39
|
+
def test_serializer_gets_id
|
40
|
+
run_generator
|
41
|
+
|
42
|
+
assert_file "app/serializers/account_serializer.rb" do |content|
|
43
|
+
if RUBY_VERSION =~ /1.8/
|
44
|
+
assert_match /def id/, content
|
45
|
+
else
|
46
|
+
assert_no_match /def id/, content
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
39
51
|
# def test_uses_namespace_application_serializer_if_one_exists
|
40
52
|
# Object.const_set(:SerializerNamespace, Module.new)
|
41
53
|
# SerializerNamespace.const_set(:ApplicationSerializer, Class.new)
|
@@ -66,6 +78,8 @@ class SerializerGeneratorTest < Rails::Generators::TestCase
|
|
66
78
|
|
67
79
|
def test_with_no_attributes_does_not_add_extra_space
|
68
80
|
run_generator ["account"]
|
69
|
-
assert_file "app/serializers/account_serializer.rb"
|
81
|
+
assert_file "app/serializers/account_serializer.rb" do |content|
|
82
|
+
assert_no_match /\n\nend/, content
|
83
|
+
end
|
70
84
|
end
|
71
85
|
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
class DefaultScopeNameTest < ActionController::TestCase
|
5
|
+
TestUser = Struct.new(:name, :admin)
|
6
|
+
|
7
|
+
class UserSerializer < ActiveModel::Serializer
|
8
|
+
attributes :admin?
|
9
|
+
def admin?
|
10
|
+
current_user.admin
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class UserTestController < ActionController::Base
|
15
|
+
protect_from_forgery
|
16
|
+
|
17
|
+
before_filter { request.format = :json }
|
18
|
+
|
19
|
+
def current_user
|
20
|
+
TestUser.new('Pete', false)
|
21
|
+
end
|
22
|
+
|
23
|
+
def render_new_user
|
24
|
+
render :json => TestUser.new('pete', false), :serializer => UserSerializer
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
tests UserTestController
|
29
|
+
|
30
|
+
def test_default_scope_name
|
31
|
+
get :render_new_user
|
32
|
+
assert_equal '{"user":{"admin":false}}', @response.body
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class SerializationScopeNameTest < ActionController::TestCase
|
37
|
+
TestUser = Struct.new(:name, :admin)
|
38
|
+
|
39
|
+
class AdminUserSerializer < ActiveModel::Serializer
|
40
|
+
attributes :admin?
|
41
|
+
def admin?
|
42
|
+
current_admin.admin
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class AdminUserTestController < ActionController::Base
|
47
|
+
protect_from_forgery
|
48
|
+
|
49
|
+
serialization_scope :current_admin
|
50
|
+
before_filter { request.format = :json }
|
51
|
+
|
52
|
+
def current_admin
|
53
|
+
TestUser.new('Bob', true)
|
54
|
+
end
|
55
|
+
|
56
|
+
def render_new_user
|
57
|
+
render :json => TestUser.new('pete', false), :serializer => AdminUserSerializer
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
tests AdminUserTestController
|
62
|
+
|
63
|
+
def test_override_scope_name_with_controller
|
64
|
+
get :render_new_user
|
65
|
+
assert_equal '{"admin_user":{"admin":true}}', @response.body
|
66
|
+
end
|
67
|
+
end
|
data/test/serialization_test.rb
CHANGED
@@ -378,7 +378,7 @@ class RenderJsonTest < ActionController::TestCase
|
|
378
378
|
assert_equal '{"awesome":[]}', @response.body
|
379
379
|
end
|
380
380
|
|
381
|
-
def
|
381
|
+
def test_render_json_empty_array_with_array_serializer_root_false
|
382
382
|
ActiveModel::ArraySerializer.root = false
|
383
383
|
get :render_json_empty_array
|
384
384
|
assert_equal '[]', @response.body
|
@@ -20,6 +20,11 @@ module ActiveRecord
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
+
module Mongoid
|
24
|
+
class Criteria
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
23
28
|
class SerializerSupportTest < ActiveModel::TestCase
|
24
29
|
test "it returns nil if no serializer exists" do
|
25
30
|
assert_equal nil, RandomModel.new.active_model_serializer
|
@@ -37,5 +42,10 @@ class SerializerSupportTest < ActiveModel::TestCase
|
|
37
42
|
ActiveSupport.run_load_hooks(:active_record)
|
38
43
|
assert_equal ActiveModel::ArraySerializer, ActiveRecord::Relation.new.active_model_serializer
|
39
44
|
end
|
45
|
+
|
46
|
+
test "it automatically includes array_serializer in mongoid/criteria" do
|
47
|
+
ActiveSupport.run_load_hooks(:mongoid)
|
48
|
+
assert_equal ActiveModel::ArraySerializer, Mongoid::Criteria.new.active_model_serializer
|
49
|
+
end
|
40
50
|
end
|
41
51
|
|
data/test/serializer_test.rb
CHANGED
@@ -51,6 +51,17 @@ class SerializerTest < ActiveModel::TestCase
|
|
51
51
|
}, hash)
|
52
52
|
end
|
53
53
|
|
54
|
+
def test_attributes_method_with_unsymbolizable_key
|
55
|
+
user = User.new
|
56
|
+
user_serializer = UserAttributesWithUnsymbolizableKeySerializer.new(user, :scope => {})
|
57
|
+
|
58
|
+
hash = user_serializer.as_json
|
59
|
+
|
60
|
+
assert_equal({
|
61
|
+
:user_attributes_with_unsymbolizable_key => { :first_name => "Jose", :"last-name" => "Valim", :ok => true }
|
62
|
+
}, hash)
|
63
|
+
end
|
64
|
+
|
54
65
|
def test_attribute_method_with_name_as_serializer_prefix
|
55
66
|
object = SomeObject.new("something")
|
56
67
|
object_serializer = SomeSerializer.new(object, {})
|
@@ -318,6 +329,16 @@ class SerializerTest < ActiveModel::TestCase
|
|
318
329
|
assert_equal({ :author => nil }, serializer.new(blog, :scope => user).as_json)
|
319
330
|
end
|
320
331
|
|
332
|
+
def test_true_root
|
333
|
+
blog = Blog.new
|
334
|
+
|
335
|
+
assert_equal({
|
336
|
+
:blog_with_root => {
|
337
|
+
:author => nil,
|
338
|
+
}
|
339
|
+
}, BlogWithRootSerializer.new(blog).as_json)
|
340
|
+
end
|
341
|
+
|
321
342
|
def test_root_false_on_load_active_model_serializers
|
322
343
|
begin
|
323
344
|
ActiveSupport.on_load(:active_model_serializers) do
|
@@ -406,6 +427,33 @@ class SerializerTest < ActiveModel::TestCase
|
|
406
427
|
}, serializer.as_json)
|
407
428
|
end
|
408
429
|
|
430
|
+
def test_methods_take_priority_over_associations
|
431
|
+
post_serializer = Class.new(ActiveModel::Serializer) do
|
432
|
+
attributes :title
|
433
|
+
has_many :comments
|
434
|
+
embed :ids
|
435
|
+
|
436
|
+
def comments
|
437
|
+
object.comments[0,1]
|
438
|
+
end
|
439
|
+
end
|
440
|
+
|
441
|
+
post = Post.new(:title => "My Post")
|
442
|
+
comments = [Comment.new(:title => "Comment1", :id => 1), Comment.new(:title => "Comment2", :id => 2)]
|
443
|
+
post.comments = comments
|
444
|
+
|
445
|
+
post.class_eval do
|
446
|
+
define_method :comment_ids, lambda {
|
447
|
+
self.comments.map { |c| c.read_attribute_for_serialization(:id) }
|
448
|
+
}
|
449
|
+
end
|
450
|
+
json = post_serializer.new(post).as_json
|
451
|
+
assert_equal({
|
452
|
+
:title => "My Post",
|
453
|
+
:comment_ids => [1]
|
454
|
+
}, json)
|
455
|
+
end
|
456
|
+
|
409
457
|
def test_embed_objects
|
410
458
|
serializer = post_serializer
|
411
459
|
|
@@ -563,16 +611,17 @@ class SerializerTest < ActiveModel::TestCase
|
|
563
611
|
|
564
612
|
# Computed attributes (not real columns or associations).
|
565
613
|
def can_edit; end
|
614
|
+
def can_view; end
|
566
615
|
def drafts; end
|
567
616
|
|
568
|
-
attributes :name, :age, :can_edit
|
617
|
+
attributes :name, :age, {:can_edit => :boolean}, :can_view
|
569
618
|
has_many :posts, :serializer => Class.new
|
570
619
|
has_many :drafts, :serializer => Class.new
|
571
620
|
has_one :parent, :serializer => Class.new
|
572
621
|
end
|
573
622
|
|
574
623
|
assert_equal serializer.schema, {
|
575
|
-
:attributes => { :name => :string, :age => :integer, :can_edit => nil },
|
624
|
+
:attributes => { :name => :string, :age => :integer, :can_edit => :boolean, :can_view => nil },
|
576
625
|
:associations => {
|
577
626
|
:posts => { :has_many => :posts },
|
578
627
|
:drafts => nil,
|
@@ -1076,7 +1125,7 @@ class SerializerTest < ActiveModel::TestCase
|
|
1076
1125
|
:name => 'logo.png',
|
1077
1126
|
:url => 'http://example.com/logo.png',
|
1078
1127
|
:attachable => {
|
1079
|
-
:type => :email,
|
1128
|
+
:type => :email,
|
1080
1129
|
:id => 1
|
1081
1130
|
}},
|
1082
1131
|
:emails => [{
|
@@ -1310,4 +1359,94 @@ class SerializerTest < ActiveModel::TestCase
|
|
1310
1359
|
]
|
1311
1360
|
}, actual)
|
1312
1361
|
end
|
1362
|
+
|
1363
|
+
def test_inheritance_does_not_used_cached_attributes
|
1364
|
+
parent = Class.new(ActiveModel::Serializer) do
|
1365
|
+
attributes :title
|
1366
|
+
end
|
1367
|
+
|
1368
|
+
child = Class.new(parent) do
|
1369
|
+
attributes :body
|
1370
|
+
end
|
1371
|
+
|
1372
|
+
data_class = Class.new do
|
1373
|
+
attr_accessor :title, :body
|
1374
|
+
end
|
1375
|
+
|
1376
|
+
item = data_class.new
|
1377
|
+
item.title = "title"
|
1378
|
+
item.body = "body"
|
1379
|
+
|
1380
|
+
2.times do
|
1381
|
+
assert_equal({:title => "title"},
|
1382
|
+
parent.new(item).attributes)
|
1383
|
+
assert_equal({:body => "body", :title => "title"},
|
1384
|
+
child.new(item).attributes)
|
1385
|
+
end
|
1386
|
+
|
1387
|
+
end
|
1388
|
+
|
1389
|
+
def test_scope_name_method
|
1390
|
+
serializer = Class.new(ActiveModel::Serializer) do
|
1391
|
+
def has_permission?
|
1392
|
+
current_user.super_user?
|
1393
|
+
end
|
1394
|
+
end
|
1395
|
+
|
1396
|
+
user = User.new
|
1397
|
+
user.superuser = true
|
1398
|
+
post = Post.new(:title => 'Foo')
|
1399
|
+
|
1400
|
+
a_serializer = serializer.new(post, :scope => user, :scope_name => :current_user)
|
1401
|
+
assert a_serializer.has_permission?
|
1402
|
+
end
|
1403
|
+
|
1404
|
+
def test_only_option_filters_attributes_and_associations
|
1405
|
+
post = Post.new(:title => "New Post", :body => "Body of new post")
|
1406
|
+
comments = [Comment.new(:title => "Comment1")]
|
1407
|
+
post.comments = comments
|
1408
|
+
|
1409
|
+
post_serializer = PostSerializer.new(post, :only => :title)
|
1410
|
+
|
1411
|
+
assert_equal({
|
1412
|
+
:post => {
|
1413
|
+
:title => "New Post"
|
1414
|
+
}
|
1415
|
+
}, post_serializer.as_json)
|
1416
|
+
end
|
1417
|
+
|
1418
|
+
def test_except_option_filters_attributes_and_associations
|
1419
|
+
post = Post.new(:title => "New Post", :body => "Body of new post")
|
1420
|
+
comments = [Comment.new(:title => "Comment1")]
|
1421
|
+
post.comments = comments
|
1422
|
+
|
1423
|
+
post_serializer = PostSerializer.new(post, :except => [:body, :comments])
|
1424
|
+
|
1425
|
+
assert_equal({
|
1426
|
+
:post => {
|
1427
|
+
:title => "New Post"
|
1428
|
+
}
|
1429
|
+
}, post_serializer.as_json)
|
1430
|
+
end
|
1431
|
+
|
1432
|
+
def test_only_option_takes_precedence_over_custom_defined_include_methods
|
1433
|
+
user = User.new
|
1434
|
+
|
1435
|
+
post = Post.new(:title => "New Post", :body => "Body of new post", :author => "Sausage King")
|
1436
|
+
comments = [Comment.new(:title => "Comment")]
|
1437
|
+
post.comments = comments
|
1438
|
+
|
1439
|
+
post_serializer = PostWithMultipleConditionalsSerializer.new(post, :scope => user, :only => :title)
|
1440
|
+
|
1441
|
+
# comments enabled
|
1442
|
+
post.comments_disabled = false
|
1443
|
+
# superuser - should see author
|
1444
|
+
user.superuser = true
|
1445
|
+
|
1446
|
+
assert_equal({
|
1447
|
+
:post => {
|
1448
|
+
:title => "New Post"
|
1449
|
+
}
|
1450
|
+
}, post_serializer.as_json)
|
1451
|
+
end
|
1313
1452
|
end
|
data/test/test_fakes.rb
CHANGED
@@ -70,6 +70,14 @@ class UserAttributesWithSomeKeySerializer < ActiveModel::Serializer
|
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
|
+
class UserAttributesWithUnsymbolizableKeySerializer < ActiveModel::Serializer
|
74
|
+
attributes :first_name, :last_name => :"last-name"
|
75
|
+
|
76
|
+
def serializable_hash
|
77
|
+
attributes.merge(:ok => true).merge(options[:scope])
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
73
81
|
class DefaultUserSerializer < ActiveModel::Serializer
|
74
82
|
attributes :first_name, :last_name
|
75
83
|
end
|
@@ -146,6 +154,10 @@ class BlogSerializer < ActiveModel::Serializer
|
|
146
154
|
has_one :author, :serializer => AuthorSerializer
|
147
155
|
end
|
148
156
|
|
157
|
+
class BlogWithRootSerializer < BlogSerializer
|
158
|
+
root true
|
159
|
+
end
|
160
|
+
|
149
161
|
class CustomPostSerializer < ActiveModel::Serializer
|
150
162
|
attributes :title
|
151
163
|
end
|