cheap_ams 0.10.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.travis.yml +26 -0
  4. data/CHANGELOG.md +13 -0
  5. data/CONTRIBUTING.md +31 -0
  6. data/Gemfile +35 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +348 -0
  9. data/Rakefile +12 -0
  10. data/appveyor.yml +25 -0
  11. data/cheap_ams.gemspec +49 -0
  12. data/docs/README.md +27 -0
  13. data/docs/general/adapters.md +51 -0
  14. data/docs/general/getting_started.md +73 -0
  15. data/docs/howto/add_pagination_links.md +112 -0
  16. data/docs/howto/add_root_key.md +51 -0
  17. data/lib/action_controller/serialization.rb +62 -0
  18. data/lib/active_model/serializable_resource.rb +84 -0
  19. data/lib/active_model/serializer/adapter/flatten_json.rb +19 -0
  20. data/lib/active_model/serializer/adapter/fragment_cache.rb +82 -0
  21. data/lib/active_model/serializer/adapter/json/fragment_cache.rb +16 -0
  22. data/lib/active_model/serializer/adapter/json.rb +53 -0
  23. data/lib/active_model/serializer/adapter/json_api/fragment_cache.rb +24 -0
  24. data/lib/active_model/serializer/adapter/json_api/pagination_links.rb +58 -0
  25. data/lib/active_model/serializer/adapter/json_api.rb +183 -0
  26. data/lib/active_model/serializer/adapter/null.rb +11 -0
  27. data/lib/active_model/serializer/adapter.rb +98 -0
  28. data/lib/active_model/serializer/array_serializer.rb +35 -0
  29. data/lib/active_model/serializer/association.rb +21 -0
  30. data/lib/active_model/serializer/associations.rb +97 -0
  31. data/lib/active_model/serializer/belongs_to_reflection.rb +10 -0
  32. data/lib/active_model/serializer/collection_reflection.rb +7 -0
  33. data/lib/active_model/serializer/configuration.rb +14 -0
  34. data/lib/active_model/serializer/fieldset.rb +42 -0
  35. data/lib/active_model/serializer/has_many_reflection.rb +10 -0
  36. data/lib/active_model/serializer/has_one_reflection.rb +10 -0
  37. data/lib/active_model/serializer/lint.rb +131 -0
  38. data/lib/active_model/serializer/railtie.rb +9 -0
  39. data/lib/active_model/serializer/reflection.rb +74 -0
  40. data/lib/active_model/serializer/singular_reflection.rb +7 -0
  41. data/lib/active_model/serializer/version.rb +5 -0
  42. data/lib/active_model/serializer.rb +205 -0
  43. data/lib/active_model_serializers.rb +29 -0
  44. data/lib/generators/serializer/USAGE +6 -0
  45. data/lib/generators/serializer/resource_override.rb +12 -0
  46. data/lib/generators/serializer/serializer_generator.rb +37 -0
  47. data/lib/generators/serializer/templates/serializer.rb +8 -0
  48. data/test/action_controller/adapter_selector_test.rb +53 -0
  49. data/test/action_controller/explicit_serializer_test.rb +134 -0
  50. data/test/action_controller/json_api/linked_test.rb +180 -0
  51. data/test/action_controller/json_api/pagination_test.rb +116 -0
  52. data/test/action_controller/serialization_scope_name_test.rb +67 -0
  53. data/test/action_controller/serialization_test.rb +426 -0
  54. data/test/adapter/fragment_cache_test.rb +37 -0
  55. data/test/adapter/json/belongs_to_test.rb +47 -0
  56. data/test/adapter/json/collection_test.rb +82 -0
  57. data/test/adapter/json/has_many_test.rb +47 -0
  58. data/test/adapter/json_api/belongs_to_test.rb +157 -0
  59. data/test/adapter/json_api/collection_test.rb +96 -0
  60. data/test/adapter/json_api/has_many_embed_ids_test.rb +45 -0
  61. data/test/adapter/json_api/has_many_explicit_serializer_test.rb +98 -0
  62. data/test/adapter/json_api/has_many_test.rb +145 -0
  63. data/test/adapter/json_api/has_one_test.rb +81 -0
  64. data/test/adapter/json_api/json_api_test.rb +38 -0
  65. data/test/adapter/json_api/linked_test.rb +283 -0
  66. data/test/adapter/json_api/pagination_links_test.rb +115 -0
  67. data/test/adapter/json_api/resource_type_config_test.rb +59 -0
  68. data/test/adapter/json_test.rb +47 -0
  69. data/test/adapter/null_test.rb +25 -0
  70. data/test/adapter_test.rb +52 -0
  71. data/test/array_serializer_test.rb +97 -0
  72. data/test/capture_warnings.rb +57 -0
  73. data/test/fixtures/active_record.rb +57 -0
  74. data/test/fixtures/poro.rb +266 -0
  75. data/test/generators/scaffold_controller_generator_test.rb +24 -0
  76. data/test/generators/serializer_generator_test.rb +56 -0
  77. data/test/lint_test.rb +44 -0
  78. data/test/poro_test.rb +9 -0
  79. data/test/serializable_resource_test.rb +27 -0
  80. data/test/serializers/adapter_for_test.rb +50 -0
  81. data/test/serializers/association_macros_test.rb +36 -0
  82. data/test/serializers/associations_test.rb +150 -0
  83. data/test/serializers/attribute_test.rb +62 -0
  84. data/test/serializers/attributes_test.rb +63 -0
  85. data/test/serializers/cache_test.rb +164 -0
  86. data/test/serializers/configuration_test.rb +15 -0
  87. data/test/serializers/fieldset_test.rb +26 -0
  88. data/test/serializers/meta_test.rb +121 -0
  89. data/test/serializers/options_test.rb +21 -0
  90. data/test/serializers/root_test.rb +23 -0
  91. data/test/serializers/serializer_for_test.rb +65 -0
  92. data/test/serializers/urls_test.rb +26 -0
  93. data/test/support/rails_app.rb +21 -0
  94. data/test/support/stream_capture.rb +49 -0
  95. data/test/support/test_case.rb +5 -0
  96. data/test/test_helper.rb +41 -0
  97. metadata +287 -0
@@ -0,0 +1,180 @@
1
+ require 'test_helper'
2
+
3
+ module ActionController
4
+ module Serialization
5
+ class JsonApi
6
+ class LinkedTest < ActionController::TestCase
7
+ class LinkedTestController < ActionController::Base
8
+ def setup_post
9
+ ActionController::Base.cache_store.clear
10
+ @role1 = Role.new(id: 1, name: 'admin')
11
+ @role2 = Role.new(id: 2, name: 'colab')
12
+ @author = Author.new(id: 1, name: 'Steve K.')
13
+ @author.posts = []
14
+ @author.bio = nil
15
+ @author.roles = [@role1, @role2]
16
+ @role1.author = @author
17
+ @role2.author = @author
18
+ @author2 = Author.new(id: 2, name: 'Anonymous')
19
+ @author2.posts = []
20
+ @author2.bio = nil
21
+ @author2.roles = []
22
+ @post = Post.new(id: 1, title: 'New Post', body: 'Body')
23
+ @first_comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
24
+ @second_comment = Comment.new(id: 2, body: 'ZOMG ANOTHER COMMENT')
25
+ @post.comments = [@first_comment, @second_comment]
26
+ @post.author = @author
27
+ @first_comment.post = @post
28
+ @first_comment.author = @author2
29
+ @second_comment.post = @post
30
+ @second_comment.author = nil
31
+ @post2 = Post.new(id: 2, title: "Another Post", body: "Body")
32
+ @post2.author = @author
33
+ @post2.comments = []
34
+ @blog = Blog.new(id: 1, name: "My Blog!!")
35
+ @post.blog = @blog
36
+ @post2.blog = @blog
37
+ end
38
+
39
+ def render_resource_without_include
40
+ setup_post
41
+ render json: @post, adapter: :json_api
42
+ end
43
+
44
+ def render_resource_with_include
45
+ setup_post
46
+ render json: @post, include: 'author', adapter: :json_api
47
+ end
48
+
49
+ def render_resource_with_nested_include
50
+ setup_post
51
+ render json: @post, include: 'comments.author', adapter: :json_api
52
+ end
53
+
54
+ def render_resource_with_nested_has_many_include
55
+ setup_post
56
+ render json: @post, include: ['author', 'author.roles'], adapter: :json_api
57
+ end
58
+
59
+ def render_resource_with_missing_nested_has_many_include
60
+ setup_post
61
+ @post.author = @author2 # author2 has no roles.
62
+ render json: @post, include: 'author,author.roles', adapter: :json_api
63
+ end
64
+
65
+ def render_collection_with_missing_nested_has_many_include
66
+ setup_post
67
+ @post.author = @author2
68
+ render json: [@post, @post2], include: 'author,author.roles', adapter: :json_api
69
+ end
70
+
71
+ def render_collection_without_include
72
+ setup_post
73
+ render json: [@post], adapter: :json_api
74
+ end
75
+
76
+ def render_collection_with_include
77
+ setup_post
78
+ render json: [@post], include: ['author', 'comments'], adapter: :json_api
79
+ end
80
+ end
81
+
82
+ tests LinkedTestController
83
+
84
+ def test_render_resource_without_include
85
+ get :render_resource_without_include
86
+ response = JSON.parse(@response.body)
87
+ refute response.key? 'included'
88
+ end
89
+
90
+ def test_render_resource_with_include
91
+ get :render_resource_with_include
92
+ response = JSON.parse(@response.body)
93
+ assert response.key? 'included'
94
+ assert_equal 1, response['included'].size
95
+ assert_equal 'Steve K.', response['included'].first['attributes']['name']
96
+ end
97
+
98
+ def test_render_resource_with_nested_has_many_include
99
+ get :render_resource_with_nested_has_many_include
100
+ response = JSON.parse(@response.body)
101
+ expected_linked = [
102
+ {
103
+ "id" => "1",
104
+ "type" => "authors",
105
+ "attributes" => {
106
+ "name" => "Steve K."
107
+ },
108
+ "relationships" => {
109
+ "posts" => { "data" => [] },
110
+ "roles" => { "data" => [{ "type" =>"roles", "id" => "1" }, { "type" =>"roles", "id" => "2" }] },
111
+ "bio" => { "data" => nil }
112
+ }
113
+ }, {
114
+ "id" => "1",
115
+ "type" => "roles",
116
+ "attributes" => {
117
+ "name" => "admin",
118
+ "description" => nil,
119
+ "slug" => "admin-1"
120
+ },
121
+ "relationships" => {
122
+ "author" => { "data" => { "type" =>"authors", "id" => "1" } }
123
+ }
124
+ }, {
125
+ "id" => "2",
126
+ "type" => "roles",
127
+ "attributes" => {
128
+ "name" => "colab",
129
+ "description" => nil,
130
+ "slug" => "colab-2"
131
+ },
132
+ "relationships" => {
133
+ "author" => { "data" => { "type" =>"authors", "id" => "1" } }
134
+ }
135
+ }
136
+ ]
137
+ assert_equal expected_linked, response['included']
138
+ end
139
+
140
+ def test_render_resource_with_nested_include
141
+ get :render_resource_with_nested_include
142
+ response = JSON.parse(@response.body)
143
+ assert response.key? 'included'
144
+ assert_equal 1, response['included'].size
145
+ assert_equal 'Anonymous', response['included'].first['attributes']['name']
146
+ end
147
+
148
+ def test_render_collection_without_include
149
+ get :render_collection_without_include
150
+ response = JSON.parse(@response.body)
151
+ refute response.key? 'included'
152
+ end
153
+
154
+ def test_render_collection_with_include
155
+ get :render_collection_with_include
156
+ response = JSON.parse(@response.body)
157
+ assert response.key? 'included'
158
+ end
159
+
160
+ def test_render_resource_with_nested_attributes_even_when_missing_associations
161
+ get :render_resource_with_missing_nested_has_many_include
162
+ response = JSON.parse(@response.body)
163
+ assert response.key? 'included'
164
+ refute has_type?(response['included'], 'roles')
165
+ end
166
+
167
+ def test_render_collection_with_missing_nested_has_many_include
168
+ get :render_collection_with_missing_nested_has_many_include
169
+ response = JSON.parse(@response.body)
170
+ assert response.key? 'included'
171
+ assert has_type?(response['included'], 'roles')
172
+ end
173
+
174
+ def has_type?(collection, value)
175
+ collection.detect { |i| i['type'] == value}
176
+ end
177
+ end
178
+ end
179
+ end
180
+ end
@@ -0,0 +1,116 @@
1
+ require 'test_helper'
2
+ require 'will_paginate/array'
3
+ require 'kaminari'
4
+ require 'kaminari/hooks'
5
+ ::Kaminari::Hooks.init
6
+
7
+ module ActionController
8
+ module Serialization
9
+ class JsonApi
10
+ class PaginationTest < ActionController::TestCase
11
+ KAMINARI_URI = 'http://test.host/action_controller/serialization/json_api/pagination_test/pagination_test/render_pagination_using_kaminari'
12
+ WILL_PAGINATE_URI = 'http://test.host/action_controller/serialization/json_api/pagination_test/pagination_test/render_pagination_using_will_paginate'
13
+
14
+ class PaginationTestController < ActionController::Base
15
+ def setup
16
+ @array = [
17
+ Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }),
18
+ Profile.new({ name: 'Name 2', description: 'Description 2', comments: 'Comments 2' }),
19
+ Profile.new({ name: 'Name 3', description: 'Description 3', comments: 'Comments 3' })
20
+ ]
21
+ end
22
+
23
+ def using_kaminari
24
+ setup
25
+ Kaminari.paginate_array(@array).page(params[:page][:number]).per(params[:page][:size])
26
+ end
27
+
28
+ def using_will_paginate
29
+ setup
30
+ @array.paginate(page: params[:page][:number], per_page: params[:page][:size])
31
+ end
32
+
33
+ def render_pagination_using_kaminari
34
+ render json: using_kaminari, adapter: :json_api
35
+ end
36
+
37
+ def render_pagination_using_will_paginate
38
+ render json: using_will_paginate, adapter: :json_api
39
+ end
40
+
41
+ def render_array_without_pagination_links
42
+ setup
43
+ render json: @array, adapter: :json_api
44
+ end
45
+ end
46
+
47
+ tests PaginationTestController
48
+
49
+ def test_render_pagination_links_with_will_paginate
50
+ expected_links = { "self"=>"#{WILL_PAGINATE_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=1",
51
+ "first"=>"#{WILL_PAGINATE_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=1",
52
+ "prev"=>"#{WILL_PAGINATE_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=1",
53
+ "next"=>"#{WILL_PAGINATE_URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1",
54
+ "last"=>"#{WILL_PAGINATE_URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1"}
55
+
56
+ get :render_pagination_using_will_paginate, page: { number: 2, size: 1 }
57
+ response = JSON.parse(@response.body)
58
+ assert_equal expected_links, response['links']
59
+ end
60
+
61
+ def test_render_only_last_and_next_pagination_links
62
+ expected_links = { "self"=>"#{WILL_PAGINATE_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2",
63
+ "next"=>"#{WILL_PAGINATE_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=2",
64
+ "last"=>"#{WILL_PAGINATE_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=2"}
65
+ get :render_pagination_using_will_paginate, page: { number: 1, size: 2 }
66
+ response = JSON.parse(@response.body)
67
+ assert_equal expected_links, response['links']
68
+ end
69
+
70
+ def test_render_pagination_links_with_kaminari
71
+ expected_links = { "self"=>"#{KAMINARI_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=1",
72
+ "first"=>"#{KAMINARI_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=1",
73
+ "prev"=>"#{KAMINARI_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=1",
74
+ "next"=>"#{KAMINARI_URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1",
75
+ "last"=>"#{KAMINARI_URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1"}
76
+ get :render_pagination_using_kaminari, page: { number: 2, size: 1 }
77
+ response = JSON.parse(@response.body)
78
+ assert_equal expected_links, response['links']
79
+ end
80
+
81
+ def test_render_only_prev_and_first_pagination_links
82
+ expected_links = { "self"=>"#{KAMINARI_URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1",
83
+ "first"=>"#{KAMINARI_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=1",
84
+ "prev"=>"#{KAMINARI_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=1"}
85
+ get :render_pagination_using_kaminari, page: { number: 3, size: 1 }
86
+ response = JSON.parse(@response.body)
87
+ assert_equal expected_links, response['links']
88
+ end
89
+
90
+ def test_render_only_last_and_next_pagination_links_with_additional_params
91
+ expected_links = { "self"=>"#{WILL_PAGINATE_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2&teste=additional",
92
+ "next"=>"#{WILL_PAGINATE_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=2&teste=additional",
93
+ "last"=>"#{WILL_PAGINATE_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=2&teste=additional"}
94
+ get :render_pagination_using_will_paginate, page: { number: 1, size: 2 }, teste: "additional"
95
+ response = JSON.parse(@response.body)
96
+ assert_equal expected_links, response['links']
97
+ end
98
+
99
+ def test_render_only_prev_and_first_pagination_links_with_additional_params
100
+ expected_links = { "self"=>"#{KAMINARI_URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1&teste=additional",
101
+ "first"=>"#{KAMINARI_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=1&teste=additional",
102
+ "prev"=>"#{KAMINARI_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=1&teste=additional"}
103
+ get :render_pagination_using_kaminari, page: { number: 3, size: 1 }, teste: "additional"
104
+ response = JSON.parse(@response.body)
105
+ assert_equal expected_links, response['links']
106
+ end
107
+
108
+ def test_array_without_pagination_links
109
+ get :render_array_without_pagination_links, page: { number: 2, size: 1 }
110
+ response = JSON.parse(@response.body)
111
+ refute response.key? 'links'
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,67 @@
1
+ require 'test_helper'
2
+ require 'pathname'
3
+
4
+ class DefaultScopeNameTest < ActionController::TestCase
5
+ class UserSerializer < ActiveModel::Serializer
6
+ attributes :admin?
7
+ ActiveModelSerializers.silence_warnings do
8
+ def admin?
9
+ current_user.admin
10
+ end
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
+ User.new(id: 1, name: 'Pete', admin: false)
21
+ end
22
+
23
+ def render_new_user
24
+ render json: User.new(id: 1, name: 'Pete', admin: false), serializer: UserSerializer, adapter: :json_api
25
+ end
26
+ end
27
+
28
+ tests UserTestController
29
+
30
+ def test_default_scope_name
31
+ get :render_new_user
32
+ assert_equal '{"data":{"id":"1","type":"users","attributes":{"admin?":false}}}', @response.body
33
+ end
34
+ end
35
+
36
+ class SerializationScopeNameTest < ActionController::TestCase
37
+ class AdminUserSerializer < ActiveModel::Serializer
38
+ attributes :admin?
39
+ ActiveModelSerializers.silence_warnings do
40
+ def admin?
41
+ current_admin.admin
42
+ end
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
+ User.new(id: 2, name: 'Bob', admin: true)
54
+ end
55
+
56
+ def render_new_user
57
+ render json: User.new(id: 1, name: 'Pete', admin: false), serializer: AdminUserSerializer, adapter: :json_api
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 '{"data":{"id":"1","type":"users","attributes":{"admin?":true}}}', @response.body
66
+ end
67
+ end