standardapi 6.1.0 → 7.1.1

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 (41) 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 +22 -22
  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 +17 -6
  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 +110 -50
  30. data/test/standard_api/test_app/app/controllers/acl/account_acl.rb +5 -1
  31. data/test/standard_api/test_app/app/controllers/acl/camera_acl.rb +7 -0
  32. data/test/standard_api/test_app/app/controllers/acl/photo_acl.rb +13 -0
  33. data/test/standard_api/test_app/app/controllers/acl/property_acl.rb +7 -1
  34. data/test/standard_api/test_app/controllers.rb +17 -0
  35. data/test/standard_api/test_app/models.rb +59 -2
  36. data/test/standard_api/test_app/test/factories.rb +3 -0
  37. data/test/standard_api/test_app/views/sessions/create.json.jbuilder +1 -0
  38. data/test/standard_api/test_app/views/sessions/create.streamer +3 -0
  39. data/test/standard_api/test_app.rb +13 -1
  40. data/test/standard_api/test_helper.rb +100 -7
  41. metadata +52 -13
@@ -80,7 +80,7 @@ class HelpersTest < ActionView::TestCase
80
80
  account.expects(:photos_cached_at).returns(t1)
81
81
 
82
82
  assert_equal(
83
- "accounts/#{account.id}/photos-#{t1.utc.to_s(ActiveRecord::Base.cache_timestamp_format)}",
83
+ "accounts/#{account.id}/photos-#{t1.utc.to_fs(ActiveRecord::Base.cache_timestamp_format)}",
84
84
  association_cache_key(account, :photos, {})
85
85
  )
86
86
 
@@ -88,7 +88,7 @@ class HelpersTest < ActionView::TestCase
88
88
  account.expects(:photos_cached_at).returns(t1)
89
89
  account.expects(:photos_property_cached_at).returns(t2)
90
90
  assert_equal(
91
- "accounts/#{account.id}/photos-2ea683a694a33359514c41435f8f0646-#{t2.utc.to_s(ActiveRecord::Base.cache_timestamp_format)}",
91
+ "accounts/#{account.id}/photos-2ea683a694a33359514c41435f8f0646-#{t2.utc.to_fs(ActiveRecord::Base.cache_timestamp_format)}",
92
92
  association_cache_key(account, :photos, {property: {}})
93
93
  )
94
94
 
@@ -96,7 +96,7 @@ class HelpersTest < ActionView::TestCase
96
96
  account.expects(:photos_cached_at).returns(t1)
97
97
  account.expects(:photos_property_cached_at).returns(t2)
98
98
  assert_equal(
99
- "accounts/#{account.id}/photos-779c17ef027655fd8c06c3083d2df64b-#{t2.utc.to_s(ActiveRecord::Base.cache_timestamp_format)}",
99
+ "accounts/#{account.id}/photos-779c17ef027655fd8c06c3083d2df64b-#{t2.utc.to_fs(ActiveRecord::Base.cache_timestamp_format)}",
100
100
  association_cache_key(account, :photos, { "property" => { "order" => { "x" => "desc" }}})
101
101
  )
102
102
 
@@ -105,7 +105,7 @@ class HelpersTest < ActionView::TestCase
105
105
  account.expects(:photos_property_cached_at).returns(t2)
106
106
  account.expects(:photos_agents_cached_at).returns(t3)
107
107
  assert_equal(
108
- "accounts/#{account.id}/photos-abbee2d4535400c162c8dbf14bbef6d5-#{t3.utc.to_s(ActiveRecord::Base.cache_timestamp_format)}",
108
+ "accounts/#{account.id}/photos-abbee2d4535400c162c8dbf14bbef6d5-#{t3.utc.to_fs(ActiveRecord::Base.cache_timestamp_format)}",
109
109
  association_cache_key(account, :photos, {property: {}, agents: {}})
110
110
  )
111
111
 
@@ -114,7 +114,7 @@ class HelpersTest < ActionView::TestCase
114
114
  account.expects(:photos_property_cached_at).returns(t2)
115
115
  account.expects(:photos_property_agents_cached_at).returns(t3)
116
116
  assert_equal(
117
- "accounts/#{account.id}/photos-0962ae73347c5c605d329eaa25e2be49-#{t3.utc.to_s(ActiveRecord::Base.cache_timestamp_format)}",
117
+ "accounts/#{account.id}/photos-0962ae73347c5c605d329eaa25e2be49-#{t3.utc.to_fs(ActiveRecord::Base.cache_timestamp_format)}",
118
118
  association_cache_key(account, :photos, {property: {agents: {}}})
119
119
  )
120
120
 
@@ -124,7 +124,7 @@ class HelpersTest < ActionView::TestCase
124
124
  account.expects(:photos_agents_cached_at).returns(t2)
125
125
  account.expects(:photos_property_addresses_cached_at).returns(t3)
126
126
  assert_equal(
127
- "accounts/#{account.id}/photos-00ea6afe3ff68037f8b4dcdb275e2a24-#{t3.utc.to_s(ActiveRecord::Base.cache_timestamp_format)}",
127
+ "accounts/#{account.id}/photos-00ea6afe3ff68037f8b4dcdb275e2a24-#{t3.utc.to_fs(ActiveRecord::Base.cache_timestamp_format)}",
128
128
  association_cache_key(account, :photos, {property: {addresses: {}}, agents: {}})
129
129
  )
130
130
 
@@ -132,7 +132,7 @@ class HelpersTest < ActionView::TestCase
132
132
  Photo.expects(:column_names).returns(['id', 'cached_at', 'account_cached_at'])
133
133
  photo.expects(:account_cached_at).returns(t1)
134
134
  assert_equal(
135
- "accounts/#{account.id}-#{t1.utc.to_s(ActiveRecord::Base.cache_timestamp_format)}",
135
+ "accounts/#{account.id}-#{t1.utc.to_fs(ActiveRecord::Base.cache_timestamp_format)}",
136
136
  association_cache_key(photo, :account, {})
137
137
  )
138
138
 
@@ -140,7 +140,7 @@ class HelpersTest < ActionView::TestCase
140
140
  photo.expects(:account_cached_at).returns(t1)
141
141
  photo.expects(:account_photos_cached_at).returns(t2)
142
142
  assert_equal(
143
- "accounts/#{account.id}/07437ce3863467f4cd715ae1ef930f08-#{t2.utc.to_s(ActiveRecord::Base.cache_timestamp_format)}",
143
+ "accounts/#{account.id}/07437ce3863467f4cd715ae1ef930f08-#{t2.utc.to_fs(ActiveRecord::Base.cache_timestamp_format)}",
144
144
  association_cache_key(photo, :account, {photos: {}})
145
145
  )
146
146
  end
@@ -150,6 +150,7 @@ class HelpersTest < ActionView::TestCase
150
150
  assert_equal 'string', json_column_type('character varying(2)')
151
151
  assert_equal 'string', json_column_type('character varying(255)')
152
152
  assert_equal 'datetime', json_column_type('timestamp without time zone')
153
+ assert_equal 'datetime', json_column_type('timestamp(6) without time zone')
153
154
  assert_equal 'datetime', json_column_type('time without time zone')
154
155
  assert_equal 'string', json_column_type('text')
155
156
  assert_equal 'hash', json_column_type('json')
@@ -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