cm-active_model_serializers 0.10.0.rc1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.travis.yml +26 -0
  4. data/CHANGELOG.md +8 -0
  5. data/CONTRIBUTING.md +31 -0
  6. data/Gemfile +17 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +326 -0
  9. data/Rakefile +12 -0
  10. data/cm-active_model_serializers.gemspec +26 -0
  11. data/lib/action_controller/serialization.rb +62 -0
  12. data/lib/active_model/serializer.rb +261 -0
  13. data/lib/active_model/serializer/adapter.rb +87 -0
  14. data/lib/active_model/serializer/adapter/fragment_cache.rb +78 -0
  15. data/lib/active_model/serializer/adapter/json.rb +52 -0
  16. data/lib/active_model/serializer/adapter/json/fragment_cache.rb +15 -0
  17. data/lib/active_model/serializer/adapter/json_api.rb +152 -0
  18. data/lib/active_model/serializer/adapter/json_api/fragment_cache.rb +22 -0
  19. data/lib/active_model/serializer/adapter/null.rb +11 -0
  20. data/lib/active_model/serializer/array_serializer.rb +32 -0
  21. data/lib/active_model/serializer/configuration.rb +13 -0
  22. data/lib/active_model/serializer/fieldset.rb +40 -0
  23. data/lib/active_model/serializer/version.rb +5 -0
  24. data/lib/active_model_serializers.rb +18 -0
  25. data/lib/generators/serializer/USAGE +6 -0
  26. data/lib/generators/serializer/serializer_generator.rb +37 -0
  27. data/lib/generators/serializer/templates/serializer.rb +8 -0
  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 +48 -0
  35. data/test/adapter/json/collection_test.rb +73 -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 +43 -0
  48. data/test/fixtures/poro.rb +213 -0
  49. data/test/serializers/adapter_for_test.rb +50 -0
  50. data/test/serializers/associations_test.rb +127 -0
  51. data/test/serializers/attribute_test.rb +38 -0
  52. data/test/serializers/attributes_test.rb +63 -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 +65 -0
  60. data/test/serializers/urls_test.rb +26 -0
  61. data/test/test_helper.rb +38 -0
  62. metadata +195 -0
@@ -0,0 +1,6 @@
1
+ Description:
2
+ Generates a serializer for the given resource with tests.
3
+
4
+ Example:
5
+ `rails generate serializer Account name created_at`
6
+
@@ -0,0 +1,37 @@
1
+ module Rails
2
+ module Generators
3
+ class SerializerGenerator < NamedBase
4
+ source_root File.expand_path("../templates", __FILE__)
5
+ check_class_collision :suffix => "Serializer"
6
+
7
+ argument :attributes, :type => :array, :default => [], :banner => "field:type field:type"
8
+
9
+ class_option :parent, :type => :string, :desc => "The parent class for the generated serializer"
10
+
11
+ def create_serializer_file
12
+ template 'serializer.rb', File.join('app/serializers', class_path, "#{file_name}_serializer.rb")
13
+ end
14
+
15
+ private
16
+
17
+ def attributes_names
18
+ [:id] + attributes.select { |attr| !attr.reference? }.map { |a| a.name.to_sym }
19
+ end
20
+
21
+ def association_names
22
+ attributes.select { |attr| attr.reference? }.map { |a| a.name.to_sym }
23
+ end
24
+
25
+ def parent_class_name
26
+ if options[:parent]
27
+ options[:parent]
28
+ elsif defined?(::ApplicationSerializer)
29
+ "ApplicationSerializer"
30
+ else
31
+ "ActiveModel::Serializer"
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+
@@ -0,0 +1,8 @@
1
+ <% module_namespacing do -%>
2
+ class <%= class_name %>Serializer < <%= parent_class_name %>
3
+ attributes <%= attributes_names.map(&:inspect).join(", ") %>
4
+ end
5
+ <% association_names.each do |attribute| -%>
6
+ attribute :<%= attribute %>
7
+ <% end -%>
8
+ <% end -%>
@@ -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_implicit_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