standardapi 6.1.0 → 7.1.0

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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +80 -58
  3. data/lib/standard_api/access_control_list.rb +40 -6
  4. data/lib/standard_api/controller.rb +96 -28
  5. data/lib/standard_api/helpers.rb +13 -7
  6. data/lib/standard_api/middleware.rb +5 -0
  7. data/lib/standard_api/railtie.rb +17 -0
  8. data/lib/standard_api/route_helpers.rb +59 -9
  9. data/lib/standard_api/test_case/calculate_tests.rb +7 -6
  10. data/lib/standard_api/test_case/destroy_tests.rb +19 -7
  11. data/lib/standard_api/test_case/index_tests.rb +7 -13
  12. data/lib/standard_api/test_case/show_tests.rb +7 -7
  13. data/lib/standard_api/test_case/update_tests.rb +7 -6
  14. data/lib/standard_api/version.rb +1 -1
  15. data/lib/standard_api/views/application/_record.json.jbuilder +4 -3
  16. data/lib/standard_api/views/application/_record.streamer +4 -3
  17. data/lib/standard_api/views/application/_schema.json.jbuilder +20 -8
  18. data/lib/standard_api/views/application/_schema.streamer +22 -8
  19. data/lib/standard_api.rb +1 -0
  20. data/test/standard_api/caching_test.rb +2 -2
  21. data/test/standard_api/controller/include_test.rb +107 -0
  22. data/test/standard_api/controller/subresource_test.rb +157 -0
  23. data/test/standard_api/helpers_test.rb +9 -8
  24. data/test/standard_api/nested_attributes/belongs_to_test.rb +71 -0
  25. data/test/standard_api/nested_attributes/has_and_belongs_to_many_test.rb +70 -0
  26. data/test/standard_api/nested_attributes/has_many_test.rb +85 -0
  27. data/test/standard_api/nested_attributes/has_one_test.rb +71 -0
  28. data/test/standard_api/route_helpers_test.rb +56 -0
  29. data/test/standard_api/standard_api_test.rb +80 -50
  30. data/test/standard_api/test_app/app/controllers/acl/camera_acl.rb +7 -0
  31. data/test/standard_api/test_app/app/controllers/acl/photo_acl.rb +13 -0
  32. data/test/standard_api/test_app/app/controllers/acl/property_acl.rb +7 -1
  33. data/test/standard_api/test_app/controllers.rb +17 -0
  34. data/test/standard_api/test_app/models.rb +59 -2
  35. data/test/standard_api/test_app/test/factories.rb +3 -0
  36. data/test/standard_api/test_app/views/sessions/create.json.jbuilder +1 -0
  37. data/test/standard_api/test_app/views/sessions/create.streamer +3 -0
  38. data/test/standard_api/test_app.rb +12 -1
  39. data/test/standard_api/test_helper.rb +9 -0
  40. metadata +52 -13
@@ -0,0 +1,71 @@
1
+ require 'standard_api/test_helper'
2
+
3
+ module NestedAttributes
4
+ class BelongsToTest < ActionDispatch::IntegrationTest
5
+ # include StandardAPI::TestCase
6
+ include StandardAPI::Helpers
7
+
8
+
9
+ # = Create Test
10
+
11
+ test 'create record and create nested record' do
12
+ @controller = PhotosController.new
13
+ post photos_path, params: { photo: { account: {name: 'Big Ben'}} }, as: :json
14
+
15
+ assert_response :created
16
+ photo = Photo.last
17
+ assert_equal 'Big Ben', photo.account.name
18
+ end
19
+
20
+ test 'create record and update nested record' do
21
+ account = create(:account, name: 'Big Ben')
22
+
23
+ @controller = PhotosController.new
24
+ post photos_path, params: { photo: { account: {id: account.id, name: 'Little Jimmie'}} }, as: :json
25
+
26
+
27
+ assert_response :created
28
+ photo = Photo.last
29
+ assert_equal account.id, photo.account_id
30
+ assert_equal 'Little Jimmie', photo.account.name
31
+ end
32
+
33
+ # = Update Test
34
+
35
+ test 'update record and create nested record' do
36
+ photo = create(:photo)
37
+
38
+ @controller = PhotosController.new
39
+ put photo_path(photo), params: { photo: { account: {name: 'Big Ben'}} }, as: :json
40
+
41
+ assert_response :ok
42
+ photo.reload
43
+ assert_equal 'Big Ben', photo.account.name
44
+ end
45
+
46
+ test 'update record and update nested record' do
47
+ account = create(:account, name: 'Big Ben')
48
+ photo = create(:photo, account: account)
49
+
50
+ @controller = PhotosController.new
51
+ put photo_path(photo), params: { photo: { account: {name: 'Little Jimmie'}} }, as: :json
52
+
53
+ assert_response :ok
54
+ photo.reload
55
+ assert_equal 'Little Jimmie', photo.account.name
56
+ end
57
+
58
+ test 'update record and set relation to nil' do
59
+ account = create(:account, name: 'Big Ben')
60
+ photo = create(:photo, account: account)
61
+
62
+ @controller = PhotosController.new
63
+ put photo_path(photo), params: { photo: { account: nil} }, as: :json
64
+
65
+ assert_response :ok
66
+ photo.reload
67
+ assert_nil photo.account
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,70 @@
1
+ require 'standard_api/test_helper'
2
+
3
+ module NestedAttributes
4
+ class HasAndBelongsToManyTest < ActionDispatch::IntegrationTest
5
+ # include StandardAPI::TestCase
6
+ include StandardAPI::Helpers
7
+
8
+
9
+ # = Create Test
10
+
11
+ test 'create record and create nested record' do
12
+ @controller = PropertiesController.new
13
+ post properties_path, params: { property: { name: 'Beach House', photos: [{format: 'image/jpeg'}]} }, as: :json
14
+
15
+ assert_response :created
16
+ property = Property.last
17
+ assert_equal 'Beach House', property.name
18
+ assert_equal ['image/jpeg'], property.photos.map(&:format)
19
+ end
20
+
21
+ test 'create record and update nested record' do
22
+ photo = create(:photo, format: 'image/png')
23
+
24
+ @controller = PropertiesController.new
25
+ post properties_path, params: { property: { name: 'Beach House', photos: [{id: photo.id, format: 'image/jpeg'}] } }, as: :json
26
+
27
+ assert_response :created
28
+ property = Property.last
29
+ assert_equal 'Beach House', property.name
30
+ assert_equal [photo.id], property.photos.map(&:id)
31
+ assert_equal ['image/jpeg'], property.photos.map(&:format)
32
+ assert_equal 'image/jpeg', photo.reload.format
33
+ end
34
+
35
+ # = Update Test
36
+
37
+ test 'update record and create nested record' do
38
+ property = create(:property)
39
+
40
+ @controller = PropertiesController.new
41
+ put property_path(property), params: { property: { photos: [{format: "image/tiff"}]} }, as: :json
42
+
43
+ assert_response :ok
44
+ assert_equal ["image/tiff"], property.reload.photos.map(&:format)
45
+ end
46
+
47
+ test 'update record and update nested record' do
48
+ photo = create(:photo, format: 'image/gif')
49
+ property = create(:property, photos: [photo])
50
+
51
+ @controller = PropertiesController.new
52
+ put property_path(property), params: { property: { photos: [{id: photo.id, format: "image/heic"}]} }, as: :json
53
+
54
+ assert_response :ok
55
+ assert_equal ['image/heic'], property.reload.photos.map(&:format)
56
+ end
57
+
58
+ test 'update record and set relation to an empty array' do
59
+ photo = create(:photo, format: 'image/gif')
60
+ property = create(:property, photos: [photo])
61
+
62
+ @controller = PropertiesController.new
63
+ put property_path(property), params: { property: { photos: [] } }, as: :json
64
+
65
+ assert_response :ok
66
+ assert_equal [], property.reload.photos
67
+ end
68
+
69
+ end
70
+ end
@@ -0,0 +1,85 @@
1
+ require 'standard_api/test_helper'
2
+
3
+ module NestedAttributes
4
+ class HasManyTest < ActionDispatch::IntegrationTest
5
+ # include StandardAPI::TestCase
6
+ include StandardAPI::Helpers
7
+
8
+
9
+ # = Create Test
10
+
11
+ test 'create record and create nested record' do
12
+ @controller = PropertiesController.new
13
+ post properties_path, params: { property: { name: 'Beach House', accounts: [{name: 'Billabong'}]} }, as: :json
14
+
15
+ assert_response :created
16
+ property = Property.last
17
+ assert_equal 'Beach House', property.name
18
+ assert_equal ['Billabong'], property.accounts.map(&:name)
19
+ end
20
+
21
+ test 'create record and update nested record' do
22
+ account = create(:account, name: 'Coco Chanel')
23
+
24
+ @controller = PropertiesController.new
25
+ post properties_path, params: { property: { name: 'Beach House', accounts: [{id: account.id, name: 'Crazy Chanel'}]} }, as: :json
26
+
27
+ assert_response :created
28
+ property = Property.last
29
+ assert_equal [account.id], property.accounts.map(&:id)
30
+ assert_equal ['Crazy Chanel'], property.accounts.map(&:name)
31
+ assert_equal 'Crazy Chanel', account.reload.name
32
+ end
33
+
34
+ # = Update Test
35
+
36
+ test 'update record and create nested record' do
37
+ property = create(:property)
38
+
39
+ @controller = PropertiesController.new
40
+ put property_path(property), params: { property: { accounts: [{name: "Hersey's"}]} }, as: :json
41
+
42
+ assert_response :ok
43
+ assert_equal ["Hersey's"], property.accounts.map(&:name)
44
+ end
45
+
46
+ test 'update record and update nested record' do
47
+ account = create(:account, name: 'A Co.')
48
+ property = create(:property, name: 'Empire State Building', accounts: [account])
49
+
50
+ @controller = PropertiesController.new
51
+ put property_path(property), params: { property: { name: 'John Hancock Center', accounts: [{id: account.id, name: "B Co."}]} }, as: :json
52
+
53
+ assert_response :ok
54
+ property.reload
55
+ assert_equal 'John Hancock Center', property.name
56
+ assert_equal ['B Co.'], property.accounts.map(&:name)
57
+ end
58
+
59
+ test 'update record and set relation to an empty array' do
60
+ account = create(:account, name: 'A Co.')
61
+ property = create(:property, name: 'Empire State Building', accounts: [account])
62
+
63
+ @controller = PropertiesController.new
64
+ put property_path(property), params: { property: { accounts: [] } }, as: :json
65
+
66
+ assert_response :ok
67
+ property.reload
68
+ assert_equal [], property.accounts
69
+ end
70
+
71
+ test 'update record and include nested record in response' do
72
+ account = create(:account, name: 'A Co.')
73
+ property = create(:property, name: 'Empire State Building', accounts: [account])
74
+
75
+ @controller = PropertiesController.new
76
+ put property_path(property), params: { property: { name: 'John Hancock Center', accounts: [{id: account.id, name: "B Co."}]} }, as: :json
77
+
78
+ attributes = JSON.parse(response.body)
79
+ assert_response :ok
80
+ assert_equal account.id, attributes["accounts"][0]["id"]
81
+ assert_equal "B Co.", attributes["accounts"][0]["name"]
82
+ end
83
+
84
+ end
85
+ end
@@ -0,0 +1,71 @@
1
+ require 'standard_api/test_helper'
2
+
3
+ module NestedAttributes
4
+ class HasOneTest < ActionDispatch::IntegrationTest
5
+ # include StandardAPI::TestCase
6
+ include StandardAPI::Helpers
7
+
8
+
9
+ # = Create Test
10
+
11
+ test 'create record and create nested record' do
12
+ @controller = PhotosController.new
13
+
14
+ post photos_path, params: { photo: { camera: {make: 'Sony'}} }, as: :json
15
+
16
+ photo = Photo.last
17
+ assert_equal photo.id, photo.camera.photo_id
18
+ assert_equal 'Sony', photo.camera.make
19
+ end
20
+
21
+ test 'create record and update nested record' do
22
+ camera = create(:camera, make: 'Sony')
23
+
24
+ @controller = PhotosController.new
25
+ post photos_path, params: { photo: { camera: {id: camera.id, make: 'Nokia'} } }, as: :json
26
+
27
+ assert_response :created
28
+ photo = Photo.last
29
+ assert_equal photo.id, photo.camera.photo_id
30
+ assert_equal 'Nokia', photo.camera.make
31
+ end
32
+
33
+ # = Update Test
34
+
35
+ test 'update record and create nested record' do
36
+ photo = create(:photo)
37
+
38
+ @controller = PhotosController.new
39
+ put photo_path(photo), params: { photo: { camera: {make: 'Canon'}} }, as: :json
40
+
41
+ assert_response :ok
42
+ photo.reload
43
+ assert_equal 'Canon', photo.camera.make
44
+ end
45
+
46
+ test 'update record and update nested record' do
47
+ camera = create(:camera, make: 'Leica')
48
+ photo = create(:photo, camera: camera)
49
+
50
+ @controller = PhotosController.new
51
+ put photo_path(photo), params: { photo: { camera: {make: 'Nokia'}} }, as: :json
52
+
53
+ assert_response :ok
54
+ photo.reload
55
+ assert_equal 'Nokia', photo.camera.make
56
+ end
57
+
58
+ test 'update record and set relation to nil' do
59
+ camera = create(:camera, make: 'Leica')
60
+ photo = create(:photo, camera: camera)
61
+
62
+ @controller = PhotosController.new
63
+ put photo_path(photo), params: { photo: { camera: nil} }, as: :json
64
+
65
+ assert_response :ok
66
+ photo.reload
67
+ assert_nil photo.camera
68
+ end
69
+
70
+ end
71
+ end
@@ -30,4 +30,60 @@ class RouteHelpersTest < ActionDispatch::IntegrationTest
30
30
  assert_routing({ path: '/photos/1/properties/1', method: :delete }, { controller: 'photos', action: 'remove_resource', id: '1', relationship: 'properties', resource_id: '1' })
31
31
  end
32
32
 
33
+ test "standard_resources with only option" do
34
+ with_routing do |set|
35
+ set.draw do
36
+ standard_resources :photos, only: [ :index, :show ]
37
+ end
38
+ assert_routing({ path: '/photos', method: :get }, { controller: 'photos', action: 'index' })
39
+ assert_routing({ path: '/photos/1', method: :get }, { controller: 'photos', action: 'show', id: '1' })
40
+ assert_equal 2, set.routes.size
41
+ end
42
+ end
43
+
44
+ test "standard_resources with except option" do
45
+ with_routing do |set|
46
+ set.draw do
47
+ standard_resources :photos, except: [ :destroy ]
48
+ end
49
+ assert_routing({ path: '/photos', method: :get }, { controller: 'photos', action: 'index' })
50
+ assert_routing({ path: '/photos/1', method: :get }, { controller: 'photos', action: 'show', id: '1' })
51
+ assert_routing({ path: '/photos/new', method: :get }, { controller: 'photos', action: 'new' })
52
+ assert_routing({ path: '/photos', method: :post }, { controller: 'photos', action: 'create' })
53
+ assert_routing({ path: '/photos/1', method: :put }, { controller: 'photos', action: 'update', id: '1' })
54
+ assert_routing({ path: '/photos/1', method: :patch }, { controller: 'photos', action: 'update', id: '1' })
55
+ assert_routing({ path: '/photos/schema', method: :get }, { controller: 'photos', action: 'schema' })
56
+ assert_routing({ path: '/photos/calculate', method: :get }, { controller: 'photos', action: 'calculate' })
57
+ assert_routing({ path: '/photos/1/properties/1', method: :post }, { controller: 'photos', action: 'add_resource', id: '1', relationship: 'properties', resource_id: '1' })
58
+ assert_routing({ path: '/photos/1/properties/1', method: :delete }, { controller: 'photos', action: 'remove_resource', id: '1', relationship: 'properties', resource_id: '1' })
59
+ assert_routing({ path: '/photos/1/properties', method: :post }, { controller: 'photos', action: 'create_resource', id: '1', relationship: 'properties' })
60
+ assert_equal 12, set.routes.size
61
+ end
62
+ end
63
+
64
+ test "standard_resource with only option" do
65
+ with_routing do |set|
66
+ set.draw do
67
+ standard_resource :accounts, only: :show
68
+ end
69
+ assert_routing({ path: '/accounts', method: :get }, { controller: 'accounts', action: 'show' })
70
+ assert_equal 1, set.routes.size
71
+ end
72
+ end
73
+
74
+ test "standard_resource with except option" do
75
+ with_routing do |set|
76
+ set.draw do
77
+ standard_resource :accounts, except: [ :destroy ]
78
+ end
79
+ assert_routing({ path: '/accounts', method: :get }, { controller: 'accounts', action: 'show' })
80
+ assert_routing({ path: '/accounts/new', method: :get }, { controller: 'accounts', action: 'new' })
81
+ assert_routing({ path: '/accounts', method: :post }, { controller: 'accounts', action: 'create' })
82
+ assert_routing({ path: '/accounts', method: :put }, { controller: 'accounts', action: 'update' })
83
+ assert_routing({ path: '/accounts', method: :patch }, { controller: 'accounts', action: 'update' })
84
+ assert_routing({ path: '/accounts/schema', method: :get }, { controller: 'accounts', action: 'schema' })
85
+ assert_routing({ path: '/accounts/calculate', method: :get }, { controller: 'accounts', action: 'calculate' })
86
+ assert_equal 10, set.routes.size
87
+ end
88
+ end
33
89
  end
@@ -92,18 +92,33 @@ class PropertiesControllerTest < ActionDispatch::IntegrationTest
92
92
  assert_equal @controller.send(:model_includes), []
93
93
  end
94
94
 
95
- test 'Controller#model_params defaults to []' do
95
+ test 'Controller#model_params defaults to ActionController::Parameters' do
96
+ @controller = DocumentsController.new
97
+ @controller.params = ActionController::Parameters.new
98
+ assert_equal @controller.send(:model_params), ActionController::Parameters.new
99
+ end
100
+
101
+ test 'Controller#model_params defaults to ActionController::Parameters when no resource_attributes' do
96
102
  @controller = ReferencesController.new
97
- @controller.params = {}
103
+ @controller.params = ActionController::Parameters.new
98
104
  assert_equal @controller.send(:model_params), ActionController::Parameters.new
99
105
  end
100
106
 
101
- test 'Controller#current_mask' do
107
+ test 'Controller#mask' do
102
108
  @controller = ReferencesController.new
103
- @controller.instance_variable_set('@current_mask', { 'references' => { 'subject_id' => 1 }})
109
+ @controller.define_singleton_method(:mask_for) do |table_name|
110
+ {subject_id: 1}
111
+ end
104
112
  @controller.params = {}
105
113
  assert_equal 'SELECT "references".* FROM "references" WHERE "references"."subject_id" = 1', @controller.send(:resources).to_sql
106
114
  end
115
+
116
+ test "Auto includes on a controller without a model" do
117
+ @controller = SessionsController.new
118
+ assert_nil @controller.send(:model)
119
+ post sessions_path(format: :json), params: {session: {user: 'user', pass: 'pass'}}
120
+ assert_response :ok
121
+ end
107
122
 
108
123
  test 'ApplicationController#schema.json' do
109
124
  get schema_path(format: 'json')
@@ -112,7 +127,7 @@ class PropertiesControllerTest < ActionDispatch::IntegrationTest
112
127
  controllers = ApplicationController.descendants
113
128
  controllers.select! { |c| c.ancestors.include?(StandardAPI::Controller) && c != StandardAPI::Controller }
114
129
 
115
- @controller.send(:models).reject { |x| x.name == 'Photo' }.each do |model|
130
+ @controller.send(:models).reject { |x| %w(Photo Document).include?(x.name) }.each do |model|
116
131
  assert_equal true, schema['models'].has_key?(model.name)
117
132
 
118
133
  model_comment = model.connection.table_comment(model.table_name)
@@ -125,7 +140,7 @@ class PropertiesControllerTest < ActionDispatch::IntegrationTest
125
140
  model.columns.each do |column|
126
141
  assert_equal json_column_type(column.sql_type), schema.dig('models', model.name, 'attributes', column.name, 'type')
127
142
  default = column.default
128
- if default then
143
+ if default
129
144
  default = model.connection.lookup_cast_type_from_column(column).deserialize(default)
130
145
  assert_equal default, schema.dig('models', model.name, 'attributes', column.name, 'default')
131
146
  else
@@ -134,11 +149,15 @@ class PropertiesControllerTest < ActionDispatch::IntegrationTest
134
149
  assert_equal column.name == model.primary_key, schema.dig('models', model.name, 'attributes', column.name, 'primary_key')
135
150
  assert_equal column.null, schema.dig('models', model.name, 'attributes', column.name, 'null')
136
151
  assert_equal column.array, schema.dig('models', model.name, 'attributes', column.name, 'array')
137
- if column.comment then
152
+ if column.comment
138
153
  assert_equal column.comment, schema.dig('models', model.name, 'attributes', column.name, 'comment')
139
154
  else
140
155
  assert_nil schema.dig('models', model.name, 'attributes', column.name, 'comment')
141
156
  end
157
+
158
+ if column.respond_to?(:auto_populated?)
159
+ assert_equal !!column.auto_populated?, schema.dig('models', model.name, 'attributes', column.name, 'auto_populated')
160
+ end
142
161
  end
143
162
  end
144
163
 
@@ -163,6 +182,26 @@ class PropertiesControllerTest < ActionDispatch::IntegrationTest
163
182
  assert_nil schema['limit']
164
183
  end
165
184
 
185
+ test 'Controller#schema.json for an enum with default' do
186
+ get schema_documents_path(format: 'json')
187
+
188
+ schema = JSON(response.body)
189
+
190
+ assert_equal true, schema.has_key?('attributes')
191
+ assert_equal 'string', schema['attributes']['level']['type']
192
+ assert_equal 'public', schema['attributes']['level']['default']
193
+ end
194
+
195
+ test 'Controller#schema.json for an enum without default' do
196
+ get schema_documents_path(format: 'json')
197
+
198
+ schema = JSON(response.body)
199
+
200
+ assert_equal true, schema.has_key?('attributes')
201
+ assert_equal 'string', schema['attributes']['rating']['type']
202
+ assert_nil schema['attributes']['rating']['default']
203
+ end
204
+
166
205
  test 'Controller#index w/o limit' do
167
206
  account = create(:account)
168
207
  get unlimited_index_path(format: 'json')
@@ -188,47 +227,6 @@ class PropertiesControllerTest < ActionDispatch::IntegrationTest
188
227
  assert_redirected_to document_path(pdf)
189
228
  end
190
229
 
191
- test 'Controller#add_resource' do
192
- property = create(:property, photos: [])
193
- photo = create(:photo)
194
-
195
- post "/properties/#{property.id}/photos/#{photo.id}"
196
- assert_equal property.photos.reload.map(&:id), [photo.id]
197
- assert_response :created
198
-
199
- post "/properties/#{property.id}/photos/9999999"
200
- assert_response :not_found
201
- end
202
-
203
- test 'Controller#add_resource with has_one' do
204
- photo = create(:document)
205
- property = create(:property)
206
- post "/properties/#{property.id}/document/#{photo.id}"
207
- assert_equal property.reload.document, photo
208
- assert_response :created
209
- end
210
-
211
- test 'Controller#remove_resource' do
212
- photo = create(:photo)
213
- property = create(:property, photos: [photo])
214
- assert_equal property.photos.reload, [photo]
215
- delete "/properties/#{property.id}/photos/#{photo.id}"
216
- assert_equal property.photos.reload, []
217
- assert_response :no_content
218
-
219
- delete "/properties/#{property.id}/photos/9999999"
220
- assert_response :not_found
221
- end
222
-
223
- test 'Controller#remove_resource with has_one' do
224
- photo = create(:document)
225
- property = create(:property, document: photo)
226
- assert_equal property.document, photo
227
- delete "/properties/#{property.id}/document/#{photo.id}"
228
- assert_nil property.reload.document
229
- assert_response :no_content
230
- end
231
-
232
230
  # = View Tests
233
231
 
234
232
  test 'rendering tables' do
@@ -236,7 +234,7 @@ class PropertiesControllerTest < ActionDispatch::IntegrationTest
236
234
  assert_response :ok
237
235
  # assert_equal ['properties', 'accounts', 'photos', 'references', 'sessions', 'unlimited'], response.parsed_body
238
236
  # Multiple 'accounts' because multiple controllers with that model for testing.
239
- assert_equal ["properties", "accounts", "documents", "photos", "references", "accounts", 'accounts'].sort, response.parsed_body.sort
237
+ assert_equal ["properties", "accounts", "documents", "photos", "references", "accounts", 'accounts', 'uuid_models'].sort, response.parsed_body.sort
240
238
  end
241
239
 
242
240
  test 'rendering null attribute' do
@@ -246,13 +244,45 @@ class PropertiesControllerTest < ActionDispatch::IntegrationTest
246
244
  assert_nil JSON(response.body)['landlord']
247
245
  end
248
246
 
247
+ test 'rendering binary attribute' do
248
+ reference = create(:reference, sha: "Hello World")
249
+ get reference_path(reference, format: 'json'), params: { id: reference.id }
250
+ assert_equal "48656c6c6f20576f726c64", JSON(response.body)['sha']
251
+ end
252
+
253
+ test 'rendering a custom binary attribute' do
254
+ reference = create(:reference, custom_binary: 2)
255
+ get reference_path(reference, format: 'json'), params: { id: reference.id }
256
+ assert_equal 2, JSON(response.body)['custom_binary']
257
+ assert_equal "\\x00000002".b,reference.custom_binary_before_type_cast
258
+ end
259
+
249
260
  test 'rendering null attribute for has_one through' do
250
261
  property = create(:property)
251
262
  get property_path(property, format: 'json'), params: { id: property.id, include: [:document] }
252
263
  assert JSON(response.body).has_key?('document')
253
264
  assert_nil JSON(response.body)['document']
254
265
  end
266
+
267
+ test 'rendering serialize_attribute' do
268
+ property = create(:property, description: 'This text will magically change')
269
+ get property_path(property, format: 'json'), params: { id: property.id, magic: true }
255
270
 
271
+ body = JSON(response.body)
272
+ assert_equal body['description'], 'See it changed!'
273
+ end
274
+
275
+ test 'rendering an enum' do
276
+ public_document = create(:document, level: 'public')
277
+
278
+ get documents_path(format: 'json'), params: { limit: 1 }
279
+ assert_equal JSON(response.body)[0]['level'], 'public'
280
+
281
+ secret_document = create(:document, level: 'secret')
282
+ get document_path(secret_document, format: 'json')
283
+ assert_equal JSON(response.body)['level'], 'secret'
284
+ end
285
+
256
286
  test '#index.json uses overridden partial' do
257
287
  create(:property, photos: [create(:photo)])
258
288
  get properties_path(format: 'json'), params: { limit: 100, include: [{:photos => { order: :id }}] }
@@ -444,7 +474,7 @@ class PropertiesControllerTest < ActionDispatch::IntegrationTest
444
474
  },
445
475
  format: 'json')
446
476
 
447
- assert_equal [photos.first.id], JSON(response.body)['photos'].map { |x| x['id'] }
477
+ assert_equal [photos.map(&:id).sort.first], JSON(response.body)['photos'].map { |x| x['id'] }
448
478
 
449
479
  get property_path(property,
450
480
  include: {
@@ -0,0 +1,7 @@
1
+ module CameraACL
2
+
3
+ def attributes
4
+ [ :make ]
5
+ end
6
+
7
+ end
@@ -0,0 +1,13 @@
1
+ module PhotoACL
2
+
3
+ def attributes
4
+ [
5
+ :format
6
+ ]
7
+ end
8
+
9
+ def nested
10
+ [ :account, :camera ]
11
+ end
12
+
13
+ end
@@ -1,5 +1,6 @@
1
1
  module PropertyACL
2
2
 
3
+ # Attributes allowed to be updated
3
4
  def attributes
4
5
  [ :name,
5
6
  :aliases,
@@ -12,16 +13,21 @@ module PropertyACL
12
13
  ]
13
14
  end
14
15
 
16
+ # Orderings allowed
15
17
  def orders
16
18
  ["id", "name", "aliases", "description", "constructed", "size", "created_at", "active"]
17
19
  end
18
20
 
21
+ # Sub resources allowed to be included in the response
19
22
  def includes
20
23
  [ :photos, :landlord, :english_name, :document ]
21
24
  end
22
25
 
26
+ # Sub resourced allowed to be set during create / update / delete if a user is
27
+ # allowed to ....
28
+ # only add to and from the relation, can also create or update the subresource
23
29
  def nested
24
- [ :photos ]
30
+ [ :photos, :accounts ]
25
31
  end
26
32
 
27
33
  end
@@ -2,6 +2,18 @@ class ApplicationController < ActionController::Base
2
2
  include StandardAPI::Controller
3
3
  include StandardAPI::AccessControlList
4
4
  prepend_view_path File.join(File.dirname(__FILE__), 'views')
5
+
6
+ helper_method :serialize_attribute
7
+
8
+ def serialize_attribute(json, record, attribute, type)
9
+ value = if attribute == 'description' && params["magic"] === "true"
10
+ 'See it changed!'
11
+ else
12
+ record.send(attribute)
13
+ end
14
+
15
+ json.set! attribute, type == :binary ? value&.unpack1('H*') : value
16
+ end
5
17
 
6
18
  end
7
19
 
@@ -48,6 +60,8 @@ class ReferencesController < ApplicationController
48
60
  end
49
61
 
50
62
  class SessionsController < ApplicationController
63
+ def create
64
+ end
51
65
  end
52
66
 
53
67
  class UnlimitedController < ApplicationController
@@ -73,3 +87,6 @@ class DefaultLimitController < ApplicationController
73
87
  end
74
88
 
75
89
  end
90
+
91
+ class UuidModelController < ApplicationController
92
+ end