sinatra_resource 0.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 (75) hide show
  1. data/.document +5 -0
  2. data/.gitignore +7 -0
  3. data/LICENSE +20 -0
  4. data/README.mdown +28 -0
  5. data/Rakefile +34 -0
  6. data/VERSION +1 -0
  7. data/examples/datacatalog/Rakefile +23 -0
  8. data/examples/datacatalog/app.rb +15 -0
  9. data/examples/datacatalog/config/config.rb +66 -0
  10. data/examples/datacatalog/config/config.yml +11 -0
  11. data/examples/datacatalog/config.ru +6 -0
  12. data/examples/datacatalog/lib/base.rb +9 -0
  13. data/examples/datacatalog/lib/resource.rb +73 -0
  14. data/examples/datacatalog/lib/roles.rb +15 -0
  15. data/examples/datacatalog/models/categorization.rb +31 -0
  16. data/examples/datacatalog/models/category.rb +28 -0
  17. data/examples/datacatalog/models/source.rb +33 -0
  18. data/examples/datacatalog/models/user.rb +51 -0
  19. data/examples/datacatalog/resources/categories.rb +32 -0
  20. data/examples/datacatalog/resources/sources.rb +35 -0
  21. data/examples/datacatalog/resources/users.rb +26 -0
  22. data/examples/datacatalog/tasks/db.rake +29 -0
  23. data/examples/datacatalog/tasks/test.rake +16 -0
  24. data/examples/datacatalog/test/helpers/assertions/assert_include.rb +17 -0
  25. data/examples/datacatalog/test/helpers/assertions/assert_not_include.rb +17 -0
  26. data/examples/datacatalog/test/helpers/lib/model_factories.rb +49 -0
  27. data/examples/datacatalog/test/helpers/lib/model_helpers.rb +30 -0
  28. data/examples/datacatalog/test/helpers/lib/request_helpers.rb +53 -0
  29. data/examples/datacatalog/test/helpers/model_test_helper.rb +5 -0
  30. data/examples/datacatalog/test/helpers/resource_test_helper.rb +5 -0
  31. data/examples/datacatalog/test/helpers/shared/api_keys.rb +48 -0
  32. data/examples/datacatalog/test/helpers/shared/common_body_responses.rb +15 -0
  33. data/examples/datacatalog/test/helpers/shared/status_codes.rb +61 -0
  34. data/examples/datacatalog/test/helpers/test_cases/model_test_case.rb +6 -0
  35. data/examples/datacatalog/test/helpers/test_cases/resource_test_case.rb +36 -0
  36. data/examples/datacatalog/test/helpers/test_helper.rb +36 -0
  37. data/examples/datacatalog/test/models/categorization_test.rb +40 -0
  38. data/examples/datacatalog/test/models/category_test.rb +35 -0
  39. data/examples/datacatalog/test/models/source_test.rb +37 -0
  40. data/examples/datacatalog/test/models/user_test.rb +77 -0
  41. data/examples/datacatalog/test/resources/categories/categories_delete_test.rb +112 -0
  42. data/examples/datacatalog/test/resources/categories/categories_get_many_test.rb +58 -0
  43. data/examples/datacatalog/test/resources/categories/categories_get_one_test.rb +75 -0
  44. data/examples/datacatalog/test/resources/categories/categories_post_test.rb +135 -0
  45. data/examples/datacatalog/test/resources/categories/categories_put_test.rb +140 -0
  46. data/examples/datacatalog/test/resources/sources/sources_delete_test.rb +112 -0
  47. data/examples/datacatalog/test/resources/sources/sources_get_many_test.rb +58 -0
  48. data/examples/datacatalog/test/resources/sources/sources_get_one_test.rb +74 -0
  49. data/examples/datacatalog/test/resources/sources/sources_post_test.rb +184 -0
  50. data/examples/datacatalog/test/resources/sources/sources_put_test.rb +227 -0
  51. data/examples/datacatalog/test/resources/users/users_delete_test.rb +134 -0
  52. data/examples/datacatalog/test/resources/users/users_get_many_test.rb +111 -0
  53. data/examples/datacatalog/test/resources/users/users_get_one_test.rb +75 -0
  54. data/examples/datacatalog/test/resources/users/users_post_test.rb +142 -0
  55. data/examples/datacatalog/test/resources/users/users_put_test.rb +171 -0
  56. data/lib/builder/helpers.rb +319 -0
  57. data/lib/builder/mongo_helpers.rb +70 -0
  58. data/lib/builder.rb +84 -0
  59. data/lib/exceptions.rb +10 -0
  60. data/lib/resource.rb +171 -0
  61. data/lib/roles.rb +163 -0
  62. data/lib/sinatra_resource.rb +6 -0
  63. data/notes/keywords.mdown +1 -0
  64. data/notes/permissions.mdown +181 -0
  65. data/notes/questions.mdown +18 -0
  66. data/notes/see_also.mdown +3 -0
  67. data/notes/synonyms.mdown +7 -0
  68. data/notes/to_do.mdown +7 -0
  69. data/notes/uniform_interface.mdown +22 -0
  70. data/sinatra_resource.gemspec +183 -0
  71. data/spec/sinatra_resource_spec.rb +7 -0
  72. data/spec/spec_helper.rb +9 -0
  73. data/tasks/spec.rake +13 -0
  74. data/tasks/yard.rake +13 -0
  75. metadata +253 -0
@@ -0,0 +1,58 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../helpers/resource_test_helper')
2
+
3
+ class CategoriesGetManyResourceTest < ResourceTestCase
4
+
5
+ def app; DataCatalog::Categories end
6
+
7
+ before do
8
+ @categories = 3.times.map do |i|
9
+ create_category(:name => "Category #{i}")
10
+ end
11
+ end
12
+
13
+ after do
14
+ @categories.each { |x| x.destroy }
15
+ end
16
+
17
+ CATEGORIES = ["Category 0", "Category 1", "Category 2"].sort
18
+
19
+ context "get /" do
20
+ context "anonymous" do
21
+ before do
22
+ get "/"
23
+ end
24
+
25
+ use "return 401 because the API key is missing"
26
+ end
27
+
28
+ context "incorrect API key" do
29
+ before do
30
+ get "/", :api_key => BAD_API_KEY
31
+ end
32
+
33
+ use "return 401 because the API key is invalid"
34
+ end
35
+ end
36
+
37
+ %w(basic curator admin).each do |role|
38
+ context "#{role} : get /" do
39
+ before do
40
+ get "/", :api_key => api_key_for(role)
41
+ end
42
+
43
+ use "return 200 Ok"
44
+
45
+ test "body should have 3 categories" do
46
+ assert_equal 3, parsed_response_body.length
47
+ end
48
+
49
+ test "body should have correct category names" do
50
+ actual = parsed_response_body.map { |e| e["name"] }
51
+ assert_equal CATEGORIES, actual.sort
52
+ end
53
+
54
+ docs_properties %w(name sources id created_at updated_at)
55
+ end
56
+ end
57
+
58
+ end
@@ -0,0 +1,75 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../helpers/resource_test_helper')
2
+
3
+ class CategoriesGetOneResourceTest < ResourceTestCase
4
+
5
+ def app; DataCatalog::Categories end
6
+
7
+ before do
8
+ @category = create_category
9
+ end
10
+
11
+ after do
12
+ @category.destroy
13
+ end
14
+
15
+ context "get /:id" do
16
+ context "anonymous" do
17
+ before do
18
+ get "/#{@category.id}"
19
+ end
20
+
21
+ use "return 401 because the API key is missing"
22
+ end
23
+
24
+ context "incorrect API key" do
25
+ before do
26
+ get "/#{@category.id}", :api_key => BAD_API_KEY
27
+ end
28
+
29
+ use "return 401 because the API key is invalid"
30
+ end
31
+ end
32
+
33
+ %w(basic curator admin).each do |role|
34
+ context "#{role} : get /:fake_id" do
35
+ before do
36
+ get "/#{FAKE_ID}", :api_key => api_key_for(role)
37
+ end
38
+
39
+ use "return 404 Not Found"
40
+ use "return an empty response body"
41
+ end
42
+
43
+ context "#{role} : get /:id" do
44
+ before do
45
+ @source = create_source
46
+ @categorization = create_categorization(
47
+ :source_id => @source.id,
48
+ :category_id => @category.id
49
+ )
50
+ get "/#{@category.id}", :api_key => api_key_for(role)
51
+ end
52
+
53
+ after do
54
+ @source.destroy
55
+ @categorization.destroy
56
+ end
57
+
58
+ use "return 200 Ok"
59
+ doc_properties %w(name id created_at updated_at sources)
60
+
61
+ test "body should have correct sources" do
62
+ expected = [
63
+ {
64
+ "id" => @source.id,
65
+ "href" => "/sources/#{@source.id}",
66
+ "title" => @source.title,
67
+ "url" => @source.url,
68
+ }
69
+ ]
70
+ assert_equal expected, parsed_response_body["sources"]
71
+ end
72
+ end
73
+ end
74
+
75
+ end
@@ -0,0 +1,135 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../helpers/resource_test_helper')
2
+
3
+ class CategoriesPostResourceTest < ResourceTestCase
4
+
5
+ include DataCatalog
6
+
7
+ def app; Categories end
8
+
9
+ before do
10
+ @category_count = Category.all.length
11
+ @valid_params = {
12
+ :name => "New Category"
13
+ }
14
+ end
15
+
16
+ shared "no new categories" do
17
+ test "should not change number of category documents in database" do
18
+ assert_equal @category_count, Category.all.length
19
+ end
20
+ end
21
+
22
+ shared "one new category" do
23
+ test "should add one category document to database" do
24
+ assert_equal @category_count + 1, Category.all.length
25
+ end
26
+ end
27
+
28
+ shared "correct Location header" do
29
+ test "should set Location header correctly" do
30
+ base_uri = Config.environment_config["base_uri"]
31
+ path = %(/categories/#{parsed_response_body["id"]})
32
+ expected = URI.join(base_uri, path).to_s
33
+ assert_equal expected, last_response.headers['Location']
34
+ end
35
+ end
36
+
37
+ context "post /" do
38
+ context "anonymous" do
39
+ before do
40
+ post "/", @valid_params
41
+ end
42
+
43
+ use "return 401 because the API key is missing"
44
+ use "no new categories"
45
+ end
46
+
47
+ context "incorrect API key" do
48
+ before do
49
+ post "/", @valid_params.merge(:api_key => BAD_API_KEY)
50
+ end
51
+
52
+ use "return 401 because the API key is invalid"
53
+ use "no new categories"
54
+ end
55
+ end
56
+
57
+ %w(basic).each do |role|
58
+ [:name].each do |missing|
59
+ context "#{role} : post / but missing #{missing}" do
60
+ before do
61
+ post "/", valid_params_for(role).delete_if { |k, v| k == missing }
62
+ end
63
+
64
+ use "return 401 Unauthorized"
65
+ use "no new categories"
66
+ end
67
+ end
68
+
69
+ [:id, :created_at, :updated_at, :sources].each do |invalid|
70
+ context "#{role} : post / but with #{invalid}" do
71
+ before do
72
+ post "/", valid_params_for(role).merge(invalid => 9)
73
+ end
74
+
75
+ use "return 401 Unauthorized"
76
+ use "no new categories"
77
+ end
78
+ end
79
+
80
+ context "#{role} : post / with valid params" do
81
+ before do
82
+ post "/", valid_params_for(role)
83
+ end
84
+
85
+ use "return 401 Unauthorized"
86
+ use "no new categories"
87
+ end
88
+ end
89
+
90
+ %w(curator admin).each do |role|
91
+ [:name].each do |missing|
92
+ context "#{role} : post / but missing #{missing}" do
93
+ before do
94
+ post "/", valid_params_for(role).delete_if { |k, v| k == missing }
95
+ end
96
+
97
+ use "return 400 Bad Request"
98
+ use "no new categories"
99
+ missing_param missing
100
+ end
101
+ end
102
+
103
+ [:id, :created_at, :updated_at, :sources].each do |invalid|
104
+ context "#{role} : post / but with #{invalid}" do
105
+ before do
106
+ post "/", valid_params_for(role).merge(invalid => 9)
107
+ end
108
+
109
+ use "return 400 Bad Request"
110
+ use "no new categories"
111
+ invalid_param invalid
112
+ end
113
+ end
114
+
115
+ context "#{role} : post / with valid params" do
116
+ before do
117
+ post "/", valid_params_for(role)
118
+ end
119
+
120
+ use "return 201 Created"
121
+ use "correct Location header"
122
+ use "one new category"
123
+ doc_properties %w(name id created_at updated_at sources)
124
+
125
+ test "should set all fields in database" do
126
+ category = Category.find_by_id(parsed_response_body["id"])
127
+ raise "Cannot find category" unless category
128
+ @valid_params.each_pair do |key, value|
129
+ assert_equal value, category[key]
130
+ end
131
+ end
132
+ end
133
+ end
134
+
135
+ end
@@ -0,0 +1,140 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../helpers/resource_test_helper')
2
+
3
+ class CategoriesPutResourceTest < ResourceTestCase
4
+
5
+ include DataCatalog
6
+
7
+ def app; Categories end
8
+
9
+ before do
10
+ @category = create_category
11
+ @category_copy = @category.dup
12
+ @valid_params = {
13
+ :name => "Changed Category"
14
+ }
15
+ end
16
+
17
+ after do
18
+ @category.destroy
19
+ end
20
+
21
+ shared "category unchanged" do
22
+ test "should not change category in database" do
23
+ assert_equal @category_copy, Category.find_by_id(@category.id)
24
+ end
25
+ end
26
+
27
+ context "put /:id" do
28
+ context "anonymous" do
29
+ before do
30
+ put "/#{@category.id}", @valid_params
31
+ end
32
+
33
+ use "return 401 because the API key is missing"
34
+ use "category unchanged"
35
+ end
36
+
37
+ context "incorrect API key" do
38
+ before do
39
+ put "/#{@category.id}", @valid_params.merge(:api_key => BAD_API_KEY)
40
+ end
41
+
42
+ use "return 401 because the API key is invalid"
43
+ use "category unchanged"
44
+ end
45
+ end
46
+
47
+ %w(basic).each do |role|
48
+ [:created_at, :updated_at, :sources].each do |invalid|
49
+ context "#{role} : put /:id but with #{invalid}" do
50
+ before do
51
+ put "/#{@category.id}", valid_params_for(role).merge(invalid => 9)
52
+ end
53
+
54
+ use "return 401 Unauthorized"
55
+ use "category unchanged"
56
+ end
57
+ end
58
+
59
+ [:name].each do |erase|
60
+ context "#{role} : put /:id but blanking out #{erase}" do
61
+ before do
62
+ put "/#{@category.id}", valid_params_for(role).merge(erase => "")
63
+ end
64
+
65
+ use "return 401 Unauthorized"
66
+ use "category unchanged"
67
+ end
68
+ end
69
+
70
+ context "#{role} : put /:id with no parameters" do
71
+ before do
72
+ put "/#{@category.id}", :api_key => api_key_for(role)
73
+ end
74
+
75
+ use "return 401 Unauthorized"
76
+ use "category unchanged"
77
+ end
78
+
79
+ context "#{role} : put /:id with valid params" do
80
+ before do
81
+ put "/#{@category.id}", valid_params_for(role)
82
+ end
83
+
84
+ use "return 401 Unauthorized"
85
+ use "category unchanged"
86
+ end
87
+ end
88
+
89
+ %w(curator admin).each do |role|
90
+ [:created_at, :updated_at, :sources].each do |invalid|
91
+ context "#{role} : put / but with #{invalid}" do
92
+ before do
93
+ put "/#{@category.id}", valid_params_for(role).merge(invalid => 9)
94
+ end
95
+
96
+ use "return 400 Bad Request"
97
+ use "category unchanged"
98
+ invalid_param invalid
99
+ end
100
+ end
101
+
102
+ [:name].each do |erase|
103
+ context "#{role} : put / but blanking out #{erase}" do
104
+ before do
105
+ put "/#{@category.id}", valid_params_for(role).merge(erase => "")
106
+ end
107
+
108
+ use "return 400 Bad Request"
109
+ use "category unchanged"
110
+ missing_param erase
111
+ end
112
+ end
113
+
114
+ context "#{role} : put /:id with no parameters" do
115
+ before do
116
+ put "/#{@category.id}", :api_key => api_key_for(role)
117
+ end
118
+
119
+ use "return 400 because no parameters were given"
120
+ use "category unchanged"
121
+ end
122
+
123
+ context "#{role} : put /:id with valid params" do
124
+ before do
125
+ put "/#{@category.id}", valid_params_for(role)
126
+ end
127
+
128
+ use "return 200 Ok"
129
+ doc_properties %w(name id created_at updated_at sources)
130
+
131
+ test "should change all fields in database" do
132
+ category = Category.find_by_id(@category.id)
133
+ @valid_params.each_pair do |key, value|
134
+ assert_equal value, category[key]
135
+ end
136
+ end
137
+ end
138
+ end
139
+
140
+ end
@@ -0,0 +1,112 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../helpers/resource_test_helper')
2
+
3
+ class SourcesDeleteResourceTest < ResourceTestCase
4
+
5
+ include DataCatalog
6
+
7
+ def app; Sources end
8
+
9
+ before do
10
+ @source = create_source
11
+ @source_count = Source.all.length
12
+ end
13
+
14
+ after do
15
+ @source.destroy
16
+ end
17
+
18
+ shared "no change in source count" do
19
+ test "should not change number of source documents in database" do
20
+ assert_equal @source_count, Source.all.length
21
+ end
22
+ end
23
+
24
+ shared "one less source" do
25
+ test "should remove one source document from database" do
26
+ assert_equal @source_count - 1, Source.all.length
27
+ end
28
+ end
29
+
30
+ context "delete /:id" do
31
+ context "anonymous" do
32
+ before do
33
+ delete "/#{@source.id}"
34
+ end
35
+
36
+ use "return 401 because the API key is missing"
37
+ use "no change in source count"
38
+ end
39
+
40
+ context "incorrect API key" do
41
+ before do
42
+ delete "/#{@source.id}", :api_key => BAD_API_KEY
43
+ end
44
+
45
+ use "return 401 because the API key is invalid"
46
+ use "no change in source count"
47
+ end
48
+ end
49
+
50
+ %w(basic).each do |role|
51
+ context "#{role} : delete /:fake_id" do
52
+ before do
53
+ delete "/#{FAKE_ID}", :api_key => api_key_for(role)
54
+ end
55
+
56
+ use "return 401 Unauthorized"
57
+ use "no change in source count"
58
+ end
59
+
60
+ context "#{role} : delete /:id" do
61
+ before do
62
+ delete "/#{@source.id}",
63
+ :api_key => api_key_for(role),
64
+ :key => "value"
65
+ end
66
+
67
+ use "return 401 Unauthorized"
68
+ use "no change in source count"
69
+ end
70
+
71
+ context "#{role} : delete /:id" do
72
+ before do
73
+ delete "/#{@source.id}", :api_key => api_key_for(role)
74
+ end
75
+
76
+ use "return 401 Unauthorized"
77
+ use "no change in source count"
78
+ end
79
+ end
80
+
81
+ %w(curator admin).each do |role|
82
+ context "#{role} : delete /:fake_id" do
83
+ before do
84
+ delete "/#{FAKE_ID}", :api_key => api_key_for(role)
85
+ end
86
+
87
+ use "return 404 Not Found"
88
+ use "no change in source count"
89
+ end
90
+
91
+ context "#{role} : delete /:id" do
92
+ before do
93
+ delete "/#{@source.id}",
94
+ :api_key => api_key_for(role),
95
+ :key => "value"
96
+ end
97
+
98
+ use "return 400 because parameters were not empty"
99
+ use "no change in source count"
100
+ end
101
+
102
+ context "#{role} : delete /:id" do
103
+ before do
104
+ delete "/#{@source.id}", :api_key => api_key_for(role)
105
+ end
106
+
107
+ use "return 204 No Content"
108
+ use "one less source"
109
+ end
110
+ end
111
+
112
+ end
@@ -0,0 +1,58 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../helpers/resource_test_helper')
2
+
3
+ class SourcesGetManyResourceTest < ResourceTestCase
4
+
5
+ def app; DataCatalog::Sources end
6
+
7
+ before do
8
+ @sources = 3.times.map do |i|
9
+ create_source(:title => "Source #{i}")
10
+ end
11
+ end
12
+
13
+ after do
14
+ @sources.each { |x| x.destroy }
15
+ end
16
+
17
+ SOURCES = ["Source 0", "Source 1", "Source 2"].sort
18
+
19
+ context "get /" do
20
+ context "anonymous" do
21
+ before do
22
+ get "/"
23
+ end
24
+
25
+ use "return 401 because the API key is missing"
26
+ end
27
+
28
+ context "incorrect API key" do
29
+ before do
30
+ get "/", :api_key => BAD_API_KEY
31
+ end
32
+
33
+ use "return 401 because the API key is invalid"
34
+ end
35
+ end
36
+
37
+ %w(basic curator admin).each do |role|
38
+ context "#{role} : get /" do
39
+ before do
40
+ get "/", :api_key => api_key_for(role)
41
+ end
42
+
43
+ use "return 200 Ok"
44
+
45
+ test "body should have 3 sources" do
46
+ assert_equal 3, parsed_response_body.length
47
+ end
48
+
49
+ test "body should have correct source titles" do
50
+ actual = parsed_response_body.map { |e| e["title"] }
51
+ assert_equal SOURCES, actual.sort
52
+ end
53
+
54
+ docs_properties %w(title url raw categories id created_at updated_at)
55
+ end
56
+ end
57
+
58
+ end
@@ -0,0 +1,74 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../helpers/resource_test_helper')
2
+
3
+ class SourcesGetOneResourceTest < ResourceTestCase
4
+
5
+ def app; DataCatalog::Sources end
6
+
7
+ before do
8
+ @source = create_source
9
+ end
10
+
11
+ after do
12
+ @source.destroy
13
+ end
14
+
15
+ context "get /:id" do
16
+ context "anonymous" do
17
+ before do
18
+ get "/#{@source.id}"
19
+ end
20
+
21
+ use "return 401 because the API key is missing"
22
+ end
23
+
24
+ context "incorrect API key" do
25
+ before do
26
+ get "/#{@source.id}", :api_key => BAD_API_KEY
27
+ end
28
+
29
+ use "return 401 because the API key is invalid"
30
+ end
31
+ end
32
+
33
+ %w(basic curator admin).each do |role|
34
+ context "#{role} : get /:fake_id" do
35
+ before do
36
+ get "/#{FAKE_ID}", :api_key => api_key_for(role)
37
+ end
38
+
39
+ use "return 404 Not Found"
40
+ use "return an empty response body"
41
+ end
42
+
43
+ context "#{role} : get /:id" do
44
+ before do
45
+ @category = create_category
46
+ @categorization = create_categorization(
47
+ :source_id => @source.id,
48
+ :category_id => @category.id
49
+ )
50
+ get "/#{@source.id}", :api_key => api_key_for(role)
51
+ end
52
+
53
+ after do
54
+ @category.destroy
55
+ @categorization.destroy
56
+ end
57
+
58
+ use "return 200 Ok"
59
+ doc_properties %w(title url raw categories id created_at updated_at)
60
+
61
+ test "body should have correct categories" do
62
+ expected = [
63
+ {
64
+ "id" => @category.id,
65
+ "href" => "/categories/#{@category.id}",
66
+ "name" => @category.name,
67
+ }
68
+ ]
69
+ assert_equal expected, parsed_response_body["categories"]
70
+ end
71
+ end
72
+ end
73
+
74
+ end