active_model_serializers 0.9.13 → 0.10.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (129) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +21 -0
  3. data/.travis.yml +27 -0
  4. data/CHANGELOG.md +8 -236
  5. data/CONTRIBUTING.md +23 -12
  6. data/Gemfile +17 -0
  7. data/{MIT-LICENSE → LICENSE.txt} +3 -2
  8. data/README.md +151 -781
  9. data/Rakefile +12 -0
  10. data/active_model_serializers.gemspec +26 -0
  11. data/lib/action_controller/serialization.rb +30 -84
  12. data/lib/active_model/serializer/adapter/fragment_cache.rb +78 -0
  13. data/lib/active_model/serializer/adapter/json/fragment_cache.rb +15 -0
  14. data/lib/active_model/serializer/adapter/json.rb +52 -0
  15. data/lib/active_model/serializer/adapter/json_api/fragment_cache.rb +22 -0
  16. data/lib/active_model/serializer/adapter/json_api.rb +152 -0
  17. data/lib/active_model/serializer/adapter/null.rb +11 -0
  18. data/lib/active_model/serializer/adapter.rb +87 -0
  19. data/lib/active_model/serializer/array_serializer.rb +32 -0
  20. data/lib/active_model/serializer/configuration.rb +13 -0
  21. data/lib/active_model/serializer/fieldset.rb +40 -0
  22. data/lib/active_model/serializer/version.rb +1 -3
  23. data/lib/active_model/serializer.rb +193 -276
  24. data/lib/active_model_serializers.rb +5 -19
  25. data/lib/generators/serializer/USAGE +6 -0
  26. data/lib/{active_model/serializer/generators → generators}/serializer/serializer_generator.rb +8 -10
  27. data/lib/{active_model/serializer/generators → generators}/serializer/templates/serializer.rb +2 -2
  28. data/test/action_controller/adapter_selector_test.rb +51 -0
  29. data/test/action_controller/explicit_serializer_test.rb +110 -0
  30. data/test/action_controller/json_api_linked_test.rb +173 -0
  31. data/test/action_controller/serialization_scope_name_test.rb +63 -0
  32. data/test/action_controller/serialization_test.rb +365 -0
  33. data/test/adapter/fragment_cache_test.rb +27 -0
  34. data/test/adapter/json/belongs_to_test.rb +41 -0
  35. data/test/adapter/json/collection_test.rb +59 -0
  36. data/test/adapter/json/has_many_test.rb +36 -0
  37. data/test/adapter/json_api/belongs_to_test.rb +147 -0
  38. data/test/adapter/json_api/collection_test.rb +89 -0
  39. data/test/adapter/json_api/has_many_embed_ids_test.rb +45 -0
  40. data/test/adapter/json_api/has_many_explicit_serializer_test.rb +98 -0
  41. data/test/adapter/json_api/has_many_test.rb +106 -0
  42. data/test/adapter/json_api/has_one_test.rb +59 -0
  43. data/test/adapter/json_api/linked_test.rb +257 -0
  44. data/test/adapter/json_test.rb +34 -0
  45. data/test/adapter/null_test.rb +25 -0
  46. data/test/adapter_test.rb +43 -0
  47. data/test/array_serializer_test.rb +29 -0
  48. data/test/fixtures/poro.rb +123 -172
  49. data/test/serializers/adapter_for_test.rb +50 -0
  50. data/test/serializers/associations_test.rb +106 -0
  51. data/test/serializers/attribute_test.rb +23 -0
  52. data/test/serializers/attributes_test.rb +28 -0
  53. data/test/serializers/cache_test.rb +128 -0
  54. data/test/serializers/configuration_test.rb +15 -0
  55. data/test/serializers/fieldset_test.rb +26 -0
  56. data/test/serializers/generators_test.rb +59 -0
  57. data/test/serializers/meta_test.rb +78 -0
  58. data/test/serializers/options_test.rb +21 -0
  59. data/test/serializers/serializer_for_test.rb +56 -0
  60. data/test/serializers/urls_test.rb +26 -0
  61. data/test/test_helper.rb +20 -10
  62. metadata +121 -148
  63. data/DESIGN.textile +0 -586
  64. data/lib/action_controller/serialization_test_case.rb +0 -82
  65. data/lib/active_model/array_serializer.rb +0 -70
  66. data/lib/active_model/default_serializer.rb +0 -30
  67. data/lib/active_model/serializable/utils.rb +0 -18
  68. data/lib/active_model/serializable.rb +0 -61
  69. data/lib/active_model/serializer/association/has_many.rb +0 -41
  70. data/lib/active_model/serializer/association/has_one.rb +0 -27
  71. data/lib/active_model/serializer/association.rb +0 -58
  72. data/lib/active_model/serializer/config.rb +0 -33
  73. data/lib/active_model/serializer/generators/resource_override.rb +0 -15
  74. data/lib/active_model/serializer/generators/serializer/USAGE +0 -9
  75. data/lib/active_model/serializer/generators/serializer/scaffold_controller_generator.rb +0 -16
  76. data/lib/active_model/serializer/generators/serializer/templates/controller.rb +0 -93
  77. data/lib/active_model/serializer/railtie.rb +0 -24
  78. data/lib/active_model/serializer_support.rb +0 -7
  79. data/test/benchmark/app.rb +0 -60
  80. data/test/benchmark/benchmarking_support.rb +0 -67
  81. data/test/benchmark/bm_active_record.rb +0 -41
  82. data/test/benchmark/setup.rb +0 -75
  83. data/test/benchmark/tmp/miniprofiler/mp_timers_6eqewtfgrhitvq5gqm25 +0 -0
  84. data/test/benchmark/tmp/miniprofiler/mp_timers_8083sx03hu72pxz1a4d0 +0 -0
  85. data/test/benchmark/tmp/miniprofiler/mp_timers_fyz2gsml4z0ph9kpoy1c +0 -0
  86. data/test/benchmark/tmp/miniprofiler/mp_timers_hjry5rc32imd42oxoi48 +0 -0
  87. data/test/benchmark/tmp/miniprofiler/mp_timers_m8fpoz2cvt3g9agz0bs3 +0 -0
  88. data/test/benchmark/tmp/miniprofiler/mp_timers_p92m2drnj1i568u3sta0 +0 -0
  89. data/test/benchmark/tmp/miniprofiler/mp_timers_qg52tpca3uesdfguee9i +0 -0
  90. data/test/benchmark/tmp/miniprofiler/mp_timers_s15t1a6mvxe0z7vjv790 +0 -0
  91. data/test/benchmark/tmp/miniprofiler/mp_timers_x8kal3d17nfds6vp4kcj +0 -0
  92. data/test/benchmark/tmp/miniprofiler/mp_views_127.0.0.1 +0 -0
  93. data/test/fixtures/active_record.rb +0 -96
  94. data/test/fixtures/template.html.erb +0 -1
  95. data/test/integration/action_controller/namespaced_serialization_test.rb +0 -105
  96. data/test/integration/action_controller/serialization_test.rb +0 -287
  97. data/test/integration/action_controller/serialization_test_case_test.rb +0 -71
  98. data/test/integration/active_record/active_record_test.rb +0 -94
  99. data/test/integration/generators/resource_generator_test.rb +0 -26
  100. data/test/integration/generators/scaffold_controller_generator_test.rb +0 -64
  101. data/test/integration/generators/serializer_generator_test.rb +0 -41
  102. data/test/test_app.rb +0 -18
  103. data/test/tmp/app/serializers/account_serializer.rb +0 -3
  104. data/test/unit/active_model/array_serializer/except_test.rb +0 -18
  105. data/test/unit/active_model/array_serializer/key_format_test.rb +0 -18
  106. data/test/unit/active_model/array_serializer/meta_test.rb +0 -53
  107. data/test/unit/active_model/array_serializer/only_test.rb +0 -18
  108. data/test/unit/active_model/array_serializer/options_test.rb +0 -16
  109. data/test/unit/active_model/array_serializer/root_test.rb +0 -102
  110. data/test/unit/active_model/array_serializer/scope_test.rb +0 -24
  111. data/test/unit/active_model/array_serializer/serialization_test.rb +0 -239
  112. data/test/unit/active_model/default_serializer_test.rb +0 -13
  113. data/test/unit/active_model/serializer/associations/build_serializer_test.rb +0 -36
  114. data/test/unit/active_model/serializer/associations_test.rb +0 -49
  115. data/test/unit/active_model/serializer/attributes_test.rb +0 -57
  116. data/test/unit/active_model/serializer/config_test.rb +0 -91
  117. data/test/unit/active_model/serializer/filter_test.rb +0 -69
  118. data/test/unit/active_model/serializer/has_many_polymorphic_test.rb +0 -189
  119. data/test/unit/active_model/serializer/has_many_test.rb +0 -265
  120. data/test/unit/active_model/serializer/has_one_and_has_many_test.rb +0 -27
  121. data/test/unit/active_model/serializer/has_one_polymorphic_test.rb +0 -196
  122. data/test/unit/active_model/serializer/has_one_test.rb +0 -253
  123. data/test/unit/active_model/serializer/key_format_test.rb +0 -25
  124. data/test/unit/active_model/serializer/meta_test.rb +0 -39
  125. data/test/unit/active_model/serializer/options_test.rb +0 -42
  126. data/test/unit/active_model/serializer/root_test.rb +0 -117
  127. data/test/unit/active_model/serializer/scope_test.rb +0 -49
  128. data/test/unit/active_model/serializer/url_helpers_test.rb +0 -36
  129. data/test/unit/active_model/serilizable_test.rb +0 -50
@@ -0,0 +1,51 @@
1
+ require 'test_helper'
2
+
3
+ module ActionController
4
+ module Serialization
5
+ class AdapterSelectorTest < ActionController::TestCase
6
+ class MyController < ActionController::Base
7
+ def render_using_default_adapter
8
+ @profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
9
+ render json: @profile
10
+ end
11
+
12
+ def render_using_adapter_override
13
+ @profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
14
+ render json: @profile, adapter: :json_api
15
+ end
16
+
17
+ def render_skipping_adapter
18
+ @profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
19
+ render json: @profile, adapter: false
20
+ end
21
+ end
22
+
23
+ tests MyController
24
+
25
+ def test_render_using_default_adapter
26
+ get :render_using_default_adapter
27
+ assert_equal '{"name":"Name 1","description":"Description 1"}', response.body
28
+ end
29
+
30
+ def test_render_using_adapter_override
31
+ get :render_using_adapter_override
32
+
33
+ expected = {
34
+ data: {
35
+ name: "Name 1",
36
+ description: "Description 1",
37
+ id: assigns(:profile).id.to_s,
38
+ type: "profiles"
39
+ }
40
+ }
41
+
42
+ assert_equal expected.to_json, response.body
43
+ end
44
+
45
+ def test_render_skipping_adapter
46
+ get :render_skipping_adapter
47
+ assert_equal '{"attributes":{"name":"Name 1","description":"Description 1","comments":"Comments 1"}}', response.body
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,110 @@
1
+ require 'test_helper'
2
+
3
+ module ActionController
4
+ module Serialization
5
+ class ExplicitSerializerTest < ActionController::TestCase
6
+ class MyController < ActionController::Base
7
+ def render_using_explicit_serializer
8
+ @profile = Profile.new(name: 'Name 1',
9
+ description: 'Description 1',
10
+ comments: 'Comments 1')
11
+ render json: @profile, serializer: ProfilePreviewSerializer
12
+ end
13
+
14
+ def render_array_using_explicit_serializer
15
+ array = [
16
+ Profile.new(name: 'Name 1',
17
+ description: 'Description 1',
18
+ comments: 'Comments 1'),
19
+ Profile.new(name: 'Name 2',
20
+ description: 'Description 2',
21
+ comments: 'Comments 2')
22
+ ]
23
+ render json: array,
24
+ serializer: PaginatedSerializer,
25
+ each_serializer: ProfilePreviewSerializer
26
+ end
27
+
28
+ def render_array_using_implicit_serializer
29
+ array = [
30
+ Profile.new(name: 'Name 1',
31
+ description: 'Description 1',
32
+ comments: 'Comments 1'),
33
+ Profile.new(name: 'Name 2',
34
+ description: 'Description 2',
35
+ comments: 'Comments 2')
36
+ ]
37
+ render json: array,
38
+ each_serializer: ProfilePreviewSerializer
39
+ end
40
+
41
+ def render_array_using_explicit_serializer_and_custom_serializers
42
+ @post = Post.new(title: 'New Post', body: 'Body')
43
+ @author = Author.new(name: 'Jane Blogger')
44
+ @author.posts = [@post]
45
+ @post.author = @author
46
+ @first_comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
47
+ @second_comment = Comment.new(id: 2, body: 'ZOMG ANOTHER COMMENT')
48
+ @post.comments = [@first_comment, @second_comment]
49
+ @first_comment.post = @post
50
+ @first_comment.author = nil
51
+ @second_comment.post = @post
52
+ @second_comment.author = nil
53
+ @blog = Blog.new(id: 23, name: 'AMS Blog')
54
+ @post.blog = @blog
55
+
56
+ render json: [@post], each_serializer: PostPreviewSerializer
57
+ end
58
+ end
59
+
60
+ tests MyController
61
+
62
+ def test_render_using_explicit_serializer
63
+ get :render_using_explicit_serializer
64
+
65
+ assert_equal 'application/json', @response.content_type
66
+ assert_equal '{"name":"Name 1"}', @response.body
67
+ end
68
+
69
+ def test_render_array_using_explicit_serializer
70
+ get :render_array_using_explicit_serializer
71
+ assert_equal 'application/json', @response.content_type
72
+
73
+ expected = {
74
+ 'paginated' => [
75
+ { 'name' => 'Name 1' },
76
+ { 'name' => 'Name 2' }
77
+ ]
78
+ }
79
+
80
+ assert_equal expected.to_json, @response.body
81
+ end
82
+
83
+ def test_render_array_using_explicit_serializer
84
+ get :render_array_using_implicit_serializer
85
+ assert_equal 'application/json', @response.content_type
86
+
87
+ expected = [
88
+ { 'name' => 'Name 1' },
89
+ { 'name' => 'Name 2' }
90
+ ]
91
+ assert_equal expected.to_json, @response.body
92
+ end
93
+
94
+ def test_render_array_using_explicit_serializer_and_custom_serializers
95
+ get :render_array_using_explicit_serializer_and_custom_serializers
96
+
97
+ expected = [
98
+ { "title" => "New Post",
99
+ "body" => "Body",
100
+ "id" => assigns(:post).id,
101
+ "comments" => [{"id" => 1}, {"id" => 2}],
102
+ "author" => { "id" => assigns(:author).id }
103
+ }
104
+ ]
105
+
106
+ assert_equal expected.to_json, @response.body
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,173 @@
1
+ require 'test_helper'
2
+
3
+ module ActionController
4
+ module Serialization
5
+ class JsonApiLinkedTest < ActionController::TestCase
6
+ class MyController < ActionController::Base
7
+ def setup_post
8
+ ActionController::Base.cache_store.clear
9
+ @role1 = Role.new(id: 1, name: 'admin')
10
+ @role2 = Role.new(id: 2, name: 'colab')
11
+ @author = Author.new(id: 1, name: 'Steve K.')
12
+ @author.posts = []
13
+ @author.bio = nil
14
+ @author.roles = [@role1, @role2]
15
+ @role1.author = @author
16
+ @role2.author = @author
17
+ @author2 = Author.new(id: 2, name: 'Anonymous')
18
+ @author2.posts = []
19
+ @author2.bio = nil
20
+ @author2.roles = []
21
+ @post = Post.new(id: 1, title: 'New Post', body: 'Body')
22
+ @first_comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
23
+ @second_comment = Comment.new(id: 2, body: 'ZOMG ANOTHER COMMENT')
24
+ @post.comments = [@first_comment, @second_comment]
25
+ @post.author = @author
26
+ @first_comment.post = @post
27
+ @first_comment.author = @author2
28
+ @second_comment.post = @post
29
+ @second_comment.author = nil
30
+ @post2 = Post.new(id: 2, title: "Another Post", body: "Body")
31
+ @post2.author = @author
32
+ @post2.comments = []
33
+ @blog = Blog.new(id: 1, name: "My Blog!!")
34
+ @post.blog = @blog
35
+ @post2.blog = @blog
36
+ end
37
+
38
+ def render_resource_without_include
39
+ setup_post
40
+ render json: @post, adapter: :json_api
41
+ end
42
+
43
+ def render_resource_with_include
44
+ setup_post
45
+ render json: @post, include: 'author', adapter: :json_api
46
+ end
47
+
48
+ def render_resource_with_nested_include
49
+ setup_post
50
+ render json: @post, include: 'comments.author', adapter: :json_api
51
+ end
52
+
53
+ def render_resource_with_nested_has_many_include
54
+ setup_post
55
+ render json: @post, include: ['author', 'author.roles'], adapter: :json_api
56
+ end
57
+
58
+ def render_resource_with_missing_nested_has_many_include
59
+ setup_post
60
+ @post.author = @author2 # author2 has no roles.
61
+ render json: @post, include: 'author,author.roles', adapter: :json_api
62
+ end
63
+
64
+ def render_collection_with_missing_nested_has_many_include
65
+ setup_post
66
+ @post.author = @author2
67
+ render json: [@post, @post2], include: 'author,author.roles', adapter: :json_api
68
+ end
69
+
70
+ def render_collection_without_include
71
+ setup_post
72
+ render json: [@post], adapter: :json_api
73
+ end
74
+
75
+ def render_collection_with_include
76
+ setup_post
77
+ render json: [@post], include: ['author', 'comments'], adapter: :json_api
78
+ end
79
+ end
80
+
81
+ tests MyController
82
+
83
+ def test_render_resource_without_include
84
+ get :render_resource_without_include
85
+ response = JSON.parse(@response.body)
86
+ refute response.key? 'included'
87
+ end
88
+
89
+ def test_render_resource_with_include
90
+ get :render_resource_with_include
91
+ response = JSON.parse(@response.body)
92
+ assert response.key? 'included'
93
+ assert_equal 1, response['included'].size
94
+ assert_equal 'Steve K.', response['included'].first['name']
95
+ end
96
+
97
+ def test_render_resource_with_nested_has_many_include
98
+ get :render_resource_with_nested_has_many_include
99
+ response = JSON.parse(@response.body)
100
+ expected_linked = [
101
+ {
102
+ "id" => "1",
103
+ "type" => "authors",
104
+ "name" => "Steve K.",
105
+ "links" => {
106
+ "posts" => { "linkage" => [] },
107
+ "roles" => { "linkage" => [{ "type" =>"roles", "id" => "1" }, { "type" =>"roles", "id" => "2" }] },
108
+ "bio" => { "linkage" => nil }
109
+ }
110
+ }, {
111
+ "id" => "1",
112
+ "type" => "roles",
113
+ "name" => "admin",
114
+ "description" => nil,
115
+ "slug" => "admin-1",
116
+ "links" => {
117
+ "author" => { "linkage" => { "type" =>"authors", "id" => "1" } }
118
+ }
119
+ }, {
120
+ "id" => "2",
121
+ "type" => "roles",
122
+ "name" => "colab",
123
+ "description" => nil,
124
+ "slug" => "colab-2",
125
+ "links" => {
126
+ "author" => { "linkage" => { "type" =>"authors", "id" => "1" } }
127
+ }
128
+ }
129
+ ]
130
+ assert_equal expected_linked, response['included']
131
+ end
132
+
133
+ def test_render_resource_with_nested_include
134
+ get :render_resource_with_nested_include
135
+ response = JSON.parse(@response.body)
136
+ assert response.key? 'included'
137
+ assert_equal 1, response['included'].size
138
+ assert_equal 'Anonymous', response['included'].first['name']
139
+ end
140
+
141
+ def test_render_collection_without_include
142
+ get :render_collection_without_include
143
+ response = JSON.parse(@response.body)
144
+ refute response.key? 'included'
145
+ end
146
+
147
+ def test_render_collection_with_include
148
+ get :render_collection_with_include
149
+ response = JSON.parse(@response.body)
150
+ assert response.key? 'included'
151
+ end
152
+
153
+ def test_render_resource_with_nested_attributes_even_when_missing_associations
154
+ get :render_resource_with_missing_nested_has_many_include
155
+ response = JSON.parse(@response.body)
156
+ assert response.key? 'included'
157
+ refute has_type?(response['included'], 'roles')
158
+ end
159
+
160
+ def test_render_collection_with_missing_nested_has_many_include
161
+ get :render_collection_with_missing_nested_has_many_include
162
+ response = JSON.parse(@response.body)
163
+ assert response.key? 'included'
164
+ assert has_type?(response['included'], 'roles')
165
+ end
166
+
167
+ def has_type?(collection, value)
168
+ collection.detect { |i| i['type'] == value}
169
+ end
170
+
171
+ end
172
+ end
173
+ end
@@ -0,0 +1,63 @@
1
+ require 'test_helper'
2
+ require 'pathname'
3
+
4
+ class DefaultScopeNameTest < ActionController::TestCase
5
+ class UserSerializer < ActiveModel::Serializer
6
+ attributes :admin?
7
+ def admin?
8
+ current_user.admin
9
+ end
10
+ end
11
+
12
+ class UserTestController < ActionController::Base
13
+ protect_from_forgery
14
+
15
+ before_filter { request.format = :json }
16
+
17
+ def current_user
18
+ User.new(id: 1, name: 'Pete', admin: false)
19
+ end
20
+
21
+ def render_new_user
22
+ render json: User.new(id: 1, name: 'Pete', admin: false), serializer: UserSerializer, adapter: :json_api
23
+ end
24
+ end
25
+
26
+ tests UserTestController
27
+
28
+ def test_default_scope_name
29
+ get :render_new_user
30
+ assert_equal '{"data":{"admin?":false,"id":"1","type":"users"}}', @response.body
31
+ end
32
+ end
33
+
34
+ class SerializationScopeNameTest < ActionController::TestCase
35
+ class AdminUserSerializer < ActiveModel::Serializer
36
+ attributes :admin?
37
+ def admin?
38
+ current_admin.admin
39
+ end
40
+ end
41
+
42
+ class AdminUserTestController < ActionController::Base
43
+ protect_from_forgery
44
+
45
+ serialization_scope :current_admin
46
+ before_filter { request.format = :json }
47
+
48
+ def current_admin
49
+ User.new(id: 2, name: 'Bob', admin: true)
50
+ end
51
+
52
+ def render_new_user
53
+ render json: User.new(id: 1, name: 'Pete', admin: false), serializer: AdminUserSerializer, adapter: :json_api
54
+ end
55
+ end
56
+
57
+ tests AdminUserTestController
58
+
59
+ def test_override_scope_name_with_controller
60
+ get :render_new_user
61
+ assert_equal '{"data":{"admin?":true,"id":"1","type":"users"}}', @response.body
62
+ end
63
+ end