sinatra_resource 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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