cheap_ams 0.10.0.rc2

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.
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