rackjson 0.2.1 → 0.3.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.
- data/README.markdown +94 -77
- data/VERSION +1 -1
- data/lib/rackjson.rb +3 -0
- data/lib/rackjson/base_document.rb +18 -0
- data/lib/rackjson/end_point.rb +4 -0
- data/lib/rackjson/filter.rb +2 -0
- data/lib/rackjson/json_document.rb +1 -12
- data/lib/rackjson/mongo_document.rb +1 -15
- data/lib/rackjson/rack/builder.rb +44 -0
- data/lib/rackjson/request.rb +1 -1
- data/lib/rackjson/resource.rb +2 -2
- data/rackjson.gemspec +6 -2
- data/test/test_collection.rb +5 -3
- data/test/test_document.rb +15 -0
- data/test/test_filter.rb +6 -0
- data/test/test_mongo_document.rb +2 -10
- data/test/test_rack_builder.rb +124 -0
- metadata +6 -2
data/README.markdown
CHANGED
@@ -12,114 +12,131 @@ RackJSON uses MongoDB for persistence so you also need to install MongoDB.
|
|
12
12
|
|
13
13
|
In your rackup file:
|
14
14
|
|
15
|
-
|
16
|
-
require rackjson
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
}
|
15
|
+
require mongo
|
16
|
+
require rackjson
|
17
|
+
|
18
|
+
expose_resource :collections => [:notes], :db => Mongo::Connection.new.db("mydb")
|
19
|
+
|
20
|
+
run lambda { |env|
|
21
|
+
[404, {'Content-Length' => '9', 'Content-Type' => 'text/plain'}, "Not Found"]
|
22
|
+
}
|
23
23
|
|
24
24
|
This will set up a RESTful resource called 'notes' at /notes which will store any JSON document.
|
25
25
|
|
26
|
-
###
|
26
|
+
### Restricting Access
|
27
27
|
|
28
|
-
|
28
|
+
There are three ways of mounting a restful resource with rackjson:
|
29
29
|
|
30
|
-
`
|
30
|
+
`expose_resource :collections => [:notes], :db => Mongo::Connection.new.db("mydb")`
|
31
31
|
|
32
|
-
`
|
33
|
-
`Connection: close`
|
34
|
-
`Date: Sun, 11 Apr 2010 11:09:40 GMT`
|
35
|
-
`Content-Type: text/plain`
|
36
|
-
`Content-Length: 0`
|
37
|
-
`Allow: GET, POST`
|
32
|
+
Using `expose_resource` won't restrict access to the resource at all, all requests by anyone will succeed.
|
38
33
|
|
39
|
-
|
34
|
+
`public_resource :collections => [:notes], :filters => [:user_id], :db => Mongo::Connection.new.db("mydb")`
|
40
35
|
|
41
|
-
`
|
36
|
+
Using `public_resource` will allow everyone to perform GET requests against the resource, however to make POST, PUT or DELETE requests the requester must have a specific session param, and will only be able to make requests to documents which match this session param. In the above example this session param is set to user_id and could be set when logging in.
|
42
37
|
|
43
|
-
`
|
44
|
-
Connection: close
|
45
|
-
Date: Sun, 11 Apr 2010 11:12:04 GMT
|
46
|
-
Content-Type: application/json
|
47
|
-
Content-Length: 2`
|
38
|
+
`public_resource :collections => [:notes], :filters => [:user_id], :db => Mongo::Connection.new.db("mydb")`
|
48
39
|
|
49
|
-
|
40
|
+
Private resource is very similar except that all requests, including GET requests must also satisfy the pre-condition of having a specific session param.
|
50
41
|
|
51
|
-
|
42
|
+
When creating resources with either the public or private resources the specified session param will be included in the document automatically.
|
52
43
|
|
53
|
-
|
44
|
+
### REST API
|
54
45
|
|
55
|
-
|
56
|
-
Connection: close
|
57
|
-
Date: Sun, 11 Apr 2010 11:14:17 GMT
|
58
|
-
Content-Type: application/json
|
59
|
-
Content-Length: 149`
|
46
|
+
To see what actions are available on the notes resource:
|
60
47
|
|
61
|
-
|
48
|
+
curl -i -XOPTIONS http://localhost:9292/notes
|
49
|
+
|
50
|
+
HTTP/1.1 200 OK
|
51
|
+
Connection: close
|
52
|
+
Date: Sun, 11 Apr 2010 11:09:40 GMT
|
53
|
+
Content-Type: text/plain
|
54
|
+
Content-Length: 0
|
55
|
+
Allow: GET, POST
|
62
56
|
|
63
|
-
|
57
|
+
Listing the existing notes:
|
64
58
|
|
65
|
-
|
59
|
+
curl -i http://localhost:9292/notes
|
60
|
+
|
61
|
+
HTTP/1.1 200 OK
|
62
|
+
Connection: close
|
63
|
+
Date: Sun, 11 Apr 2010 11:12:04 GMT
|
64
|
+
Content-Type: application/json
|
65
|
+
Content-Length: 2
|
66
|
+
|
67
|
+
[]
|
66
68
|
|
67
|
-
|
68
|
-
Connection: close
|
69
|
-
Date: Sun, 11 Apr 2010 11:16:30 GMT
|
70
|
-
Content-Type: application/json
|
71
|
-
Content-Length: 147`
|
69
|
+
Currently there are no notes, create one with a post request:
|
72
70
|
|
73
|
-
|
71
|
+
curl -i -XPOST -d'{"title":"hello world!"}' http://localhost:9292/notes
|
72
|
+
|
73
|
+
HTTP/1.1 201 Created
|
74
|
+
Connection: close
|
75
|
+
Date: Sun, 11 Apr 2010 11:14:17 GMT
|
76
|
+
Content-Type: application/json
|
77
|
+
Content-Length: 149
|
78
|
+
|
79
|
+
{"updated_at":"Sun Apr 11 12:14:17 +0100 2010","title":"hello world!","_id":"4bc1af0934701204fd000001","created_at":"Sun Apr 11 12:14:17 +0100 2010"}
|
74
80
|
|
75
|
-
|
81
|
+
RackJSON will assign an id to this resource as _id. This can be used to access this resource directly
|
76
82
|
|
77
|
-
|
83
|
+
curl -i http://localhost:9292/notes/4bc1af0934701204fd000001
|
84
|
+
|
85
|
+
HTTP/1.1 200 OK
|
86
|
+
Connection: close
|
87
|
+
Date: Sun, 11 Apr 2010 11:16:30 GMT
|
88
|
+
Content-Type: application/json
|
89
|
+
Content-Length: 147
|
90
|
+
|
91
|
+
[{"updated_at":"Sun Apr 11 11:14:17 UTC 2010","title":"hello world!","_id":"4bc1af0934701204fd000001","created_at":"Sun Apr 11 11:14:17 UTC 2010"}]
|
78
92
|
|
79
|
-
|
80
|
-
Connection: close
|
81
|
-
Date: Sun, 11 Apr 2010 11:17:27 GMT
|
82
|
-
Content-Type: application/json
|
83
|
-
Content-Length: 147`
|
93
|
+
This resource will also appear in the index of notes resources
|
84
94
|
|
85
|
-
|
95
|
+
curl -i http://localhost:9292/notes
|
96
|
+
|
97
|
+
HTTP/1.1 200 OK
|
98
|
+
Connection: close
|
99
|
+
Date: Sun, 11 Apr 2010 11:17:27 GMT
|
100
|
+
Content-Type: application/json
|
101
|
+
Content-Length: 147
|
102
|
+
|
103
|
+
[{"updated_at":"Sun Apr 11 11:14:17 UTC 2010","title":"hello world!","_id":"4bc1af0934701204fd000001","created_at":"Sun Apr 11 11:14:17 UTC 2010"}]
|
86
104
|
|
87
105
|
Update a resource using a PUT request
|
88
106
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
Connection: close
|
93
|
-
Date: Sun, 11 Apr 2010 11:25:04 GMT
|
94
|
-
Content-Type: application/json
|
95
|
-
Content-Length: 144
|
96
|
-
|
97
|
-
|
107
|
+
curl -i -XPUT -d'{"title":"updated"}' http://localhost:9292/notes/4bc1af0934701204fd000001
|
108
|
+
|
109
|
+
HTTP/1.1 200 OK
|
110
|
+
Connection: close
|
111
|
+
Date: Sun, 11 Apr 2010 11:25:04 GMT
|
112
|
+
Content-Type: application/json
|
113
|
+
Content-Length: 144
|
114
|
+
|
115
|
+
{"updated_at":"Sun Apr 11 12:25:04 +0100 2010","title":"updated","_id":"4bc1af0934701204fd000001","created_at":"Sun Apr 11 12:25:04 +0100 2010"}
|
98
116
|
|
99
117
|
A PUT request can also be used to create a resource at the given location:
|
100
118
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
Connection: close
|
105
|
-
Date: Sun, 11 Apr 2010 11:27:13 GMT
|
106
|
-
Content-Type: application/json
|
107
|
-
Content-Length: 113
|
108
|
-
|
109
|
-
|
119
|
+
curl -i -XPUT -d'{"foo":"bar"}' http://localhost:9292/notes/1
|
120
|
+
|
121
|
+
HTTP/1.1 200 OK
|
122
|
+
Connection: close
|
123
|
+
Date: Sun, 11 Apr 2010 11:27:13 GMT
|
124
|
+
Content-Type: application/json
|
125
|
+
Content-Length: 113
|
126
|
+
|
127
|
+
{"updated_at":"Sun Apr 11 12:27:13 +0100 2010","_id":1,"foo":"bar","created_at":"Sun Apr 11 12:27:13 +0100 2010"}
|
110
128
|
|
111
129
|
Finally a resource can be deleted using a DELETE request
|
112
130
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
Connection: close
|
117
|
-
Date: Sun, 11 Apr 2010 11:29:14 GMT
|
118
|
-
Content-Type: application/json
|
119
|
-
Content-Length: 12
|
120
|
-
|
121
|
-
|
122
|
-
`{"ok": "true"}`
|
131
|
+
curl -i -XDELETE http://localhost:9292/notes/1
|
132
|
+
|
133
|
+
HTTP/1.1 200 OK
|
134
|
+
Connection: close
|
135
|
+
Date: Sun, 11 Apr 2010 11:29:14 GMT
|
136
|
+
Content-Type: application/json
|
137
|
+
Content-Length: 12
|
138
|
+
|
139
|
+
{"ok": "true"}
|
123
140
|
|
124
141
|
### JSON Query
|
125
142
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/lib/rackjson.rb
CHANGED
@@ -3,9 +3,12 @@ require 'json'
|
|
3
3
|
require 'rack'
|
4
4
|
require 'mongo'
|
5
5
|
require 'time'
|
6
|
+
require 'rackjson/rack/builder'
|
6
7
|
|
7
8
|
module Rack::JSON
|
8
9
|
|
10
|
+
autoload :BaseDocument, 'rackjson/base_document'
|
11
|
+
autoload :Builder, 'rackjson/rack/builder'
|
9
12
|
autoload :EndPoint, 'rackjson/end_point'
|
10
13
|
autoload :Collection, 'rackjson/collection'
|
11
14
|
autoload :Filter, 'rackjson/filter'
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Rack::JSON
|
2
|
+
module BaseDocument
|
3
|
+
|
4
|
+
private
|
5
|
+
|
6
|
+
def set_attribute_created_at
|
7
|
+
@attributes["created_at"] = Time.now unless @attributes["created_at"]
|
8
|
+
end
|
9
|
+
|
10
|
+
def set_attributes
|
11
|
+
private_methods.each do |method|
|
12
|
+
if method.match /^set_attribute_\w*$/
|
13
|
+
send method
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/rackjson/end_point.rb
CHANGED
@@ -15,6 +15,10 @@ module Rack::JSON
|
|
15
15
|
!@methods.include?(request.request_method.downcase.to_sym)
|
16
16
|
end
|
17
17
|
|
18
|
+
def invalid_json error
|
19
|
+
render (error.class.to_s + " :" + error.message), :status => 422
|
20
|
+
end
|
21
|
+
|
18
22
|
def render body, options={}
|
19
23
|
Rack::JSON::Response.new(body, options).to_a
|
20
24
|
end
|
data/lib/rackjson/filter.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
module Rack::JSON
|
2
2
|
class JSONDocument
|
3
|
+
include Rack::JSON::BaseDocument
|
3
4
|
|
4
5
|
attr_reader :attributes
|
5
6
|
|
@@ -14,10 +15,6 @@ module Rack::JSON
|
|
14
15
|
|
15
16
|
private
|
16
17
|
|
17
|
-
def set_attribute_created_at
|
18
|
-
@attributes["created_at"] = Time.now unless @attributes["created_at"]
|
19
|
-
end
|
20
|
-
|
21
18
|
def set_attribute_dates
|
22
19
|
@attributes.each_pair do |key, value|
|
23
20
|
if value.class == String && value.match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/)
|
@@ -35,13 +32,5 @@ module Rack::JSON
|
|
35
32
|
def set_attribute_updated_at
|
36
33
|
@attributes["updated_at"] = Time.now
|
37
34
|
end
|
38
|
-
|
39
|
-
def set_attributes
|
40
|
-
private_methods.each do |method|
|
41
|
-
if method.match /^set_attribute_\w*$/
|
42
|
-
send method
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
35
|
end
|
47
36
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module Rack::JSON
|
2
2
|
class MongoDocument
|
3
|
+
include Rack::JSON::BaseDocument
|
3
4
|
|
4
5
|
attr_accessor :attributes
|
5
6
|
|
6
7
|
def initialize(row)
|
7
8
|
@attributes = row
|
8
|
-
set_created_at
|
9
9
|
set_attributes
|
10
10
|
end
|
11
11
|
|
@@ -14,19 +14,5 @@ module Rack::JSON
|
|
14
14
|
def set_attribute_ids
|
15
15
|
@attributes["_id"] = @attributes["_id"].to_s if (@attributes["_id"].is_a? BSON::ObjectID)
|
16
16
|
end
|
17
|
-
|
18
|
-
def set_created_at
|
19
|
-
if @attributes["_id"].is_a? BSON::ObjectID
|
20
|
-
@attributes["created_at"] = @attributes["_id"].generation_time unless @attributes["created_at"]
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def set_attributes
|
25
|
-
private_methods.each do |method|
|
26
|
-
if method.match /^set_attribute_\w*$/
|
27
|
-
send method
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
17
|
end
|
32
18
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Rack
|
2
|
+
class Builder
|
3
|
+
# Setup resource collections without authentication.
|
4
|
+
#
|
5
|
+
# ===Example
|
6
|
+
# expose_resource :collections => [:notes, :projects], :db => @mongo_db
|
7
|
+
#
|
8
|
+
def expose_resource options
|
9
|
+
@ins << lambda do |app|
|
10
|
+
Rack::JSON::Resource.new app, options
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Setup resource collections with public read access but write access only
|
15
|
+
# given to the owner of the document, determened from the session var passed
|
16
|
+
# as filter.
|
17
|
+
#
|
18
|
+
# ===Example
|
19
|
+
# public_resource :collections => [:notes, :projects], :db => @mongo_db, :filters => [:user_id]
|
20
|
+
#
|
21
|
+
def public_resource options
|
22
|
+
@ins << lambda do |app|
|
23
|
+
Rack::JSON::Filter.new(
|
24
|
+
Rack::JSON::Resource.new(app, options),
|
25
|
+
options.merge(:methods => [:post, :put, :delete]))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Setup resource collections with no public access. Read and write access only
|
30
|
+
# given to the owner of the document, determened from the session vars passed
|
31
|
+
# as filters.
|
32
|
+
#
|
33
|
+
# ===Example
|
34
|
+
# private_resource :collections => [:notes, :projects], :db => @mongo_db, :filters => [:user_id]
|
35
|
+
#
|
36
|
+
def private_resource options
|
37
|
+
@ins << lambda do |app|
|
38
|
+
Rack::JSON::Filter.new(
|
39
|
+
Rack::JSON::Resource.new(app, options),
|
40
|
+
options.merge(:methods => [:get, :post, :put, :delete]))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/rackjson/request.rb
CHANGED
data/lib/rackjson/resource.rb
CHANGED
@@ -57,13 +57,13 @@ module Rack::JSON
|
|
57
57
|
@collection.create(document.attributes)
|
58
58
|
render document.to_json, :status => 201
|
59
59
|
rescue JSON::ParserError => error
|
60
|
-
|
60
|
+
invalid_json error
|
61
61
|
end
|
62
62
|
|
63
63
|
def put(request)
|
64
64
|
@collection.exists?(request.resource_id) ? update(request) : upsert(request)
|
65
65
|
rescue JSON::ParserError => error
|
66
|
-
|
66
|
+
invalid_json error
|
67
67
|
end
|
68
68
|
|
69
69
|
def update(request)
|
data/rackjson.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{rackjson}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.3.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Oliver Nightingale"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-05-06}
|
13
13
|
s.description = %q{A rack end point for storing json documents.}
|
14
14
|
s.email = %q{oliver.n@new-bamboo.co.uk}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -24,6 +24,7 @@ Gem::Specification.new do |s|
|
|
24
24
|
"Rakefile",
|
25
25
|
"VERSION",
|
26
26
|
"lib/rackjson.rb",
|
27
|
+
"lib/rackjson/base_document.rb",
|
27
28
|
"lib/rackjson/collection.rb",
|
28
29
|
"lib/rackjson/document.rb",
|
29
30
|
"lib/rackjson/end_point.rb",
|
@@ -31,6 +32,7 @@ Gem::Specification.new do |s|
|
|
31
32
|
"lib/rackjson/json_document.rb",
|
32
33
|
"lib/rackjson/json_query.rb",
|
33
34
|
"lib/rackjson/mongo_document.rb",
|
35
|
+
"lib/rackjson/rack/builder.rb",
|
34
36
|
"lib/rackjson/request.rb",
|
35
37
|
"lib/rackjson/resource.rb",
|
36
38
|
"lib/rackjson/response.rb",
|
@@ -43,6 +45,7 @@ Gem::Specification.new do |s|
|
|
43
45
|
"test/test_json_document.rb",
|
44
46
|
"test/test_json_query.rb",
|
45
47
|
"test/test_mongo_document.rb",
|
48
|
+
"test/test_rack_builder.rb",
|
46
49
|
"test/test_resource.rb",
|
47
50
|
"test/test_response.rb"
|
48
51
|
]
|
@@ -60,6 +63,7 @@ Gem::Specification.new do |s|
|
|
60
63
|
"test/test_json_document.rb",
|
61
64
|
"test/test_json_query.rb",
|
62
65
|
"test/test_mongo_document.rb",
|
66
|
+
"test/test_rack_builder.rb",
|
63
67
|
"test/test_resource.rb",
|
64
68
|
"test/test_response.rb"
|
65
69
|
]
|
data/test/test_collection.rb
CHANGED
@@ -13,7 +13,9 @@ class CollectionTest < Test::Unit::TestCase
|
|
13
13
|
|
14
14
|
test "finding a single document by id" do
|
15
15
|
mongo_document = @mongo_collection.save({:testing => true, :rating => 5, :title => 'testing', :_id => 1})
|
16
|
-
assert_equal @collection.find(1).attributes, @mongo_collection.find_one(:_id => 1)
|
16
|
+
assert_equal @collection.find(1).attributes['testing'], @mongo_collection.find_one(:_id => 1)['testing']
|
17
|
+
assert_equal @collection.find(1).attributes['rating'], @mongo_collection.find_one(:_id => 1)['rating']
|
18
|
+
assert_equal @collection.find(1).attributes['title'], @mongo_collection.find_one(:_id => 1)['title']
|
17
19
|
assert_kind_of Rack::JSON::Document, @collection.find(1)
|
18
20
|
end
|
19
21
|
|
@@ -21,7 +23,7 @@ class CollectionTest < Test::Unit::TestCase
|
|
21
23
|
mongo_document = @mongo_collection.save({:testing => true, :rating => 5, :title => 'testing', :_id => 1})
|
22
24
|
mongo_results = []
|
23
25
|
@mongo_collection.find(:testing => true).each { |row| mongo_results << row }
|
24
|
-
assert_equal @collection.find(:testing => true).first.attributes, mongo_results.first
|
26
|
+
assert_equal @collection.find(:testing => true, :rating => 5).first.attributes['testing'], mongo_results.first['testing']
|
25
27
|
assert_kind_of Rack::JSON::Document, @collection.find(:testing => true).first
|
26
28
|
end
|
27
29
|
|
@@ -30,7 +32,7 @@ class CollectionTest < Test::Unit::TestCase
|
|
30
32
|
mongo_results = []
|
31
33
|
@mongo_collection.find(:testing => true, :rating => 5).each { |row| mongo_results << row }
|
32
34
|
assert_equal @collection.find(:testing => true, :rating => 5).length, mongo_results.length
|
33
|
-
assert_equal @collection.find(:testing => true, :rating => 5).first.attributes, mongo_results.first
|
35
|
+
assert_equal @collection.find(:testing => true, :rating => 5).first.attributes['testing'], mongo_results.first['testing']
|
34
36
|
end
|
35
37
|
|
36
38
|
def test_finding_no_documents_using_search_conditions
|
data/test/test_document.rb
CHANGED
@@ -44,6 +44,21 @@ class DocumentTest < Test::Unit::TestCase
|
|
44
44
|
assert_equal(Time.now.to_s, document.attributes["updated_at"].to_s)
|
45
45
|
end
|
46
46
|
|
47
|
+
test "creating from json with single nested document" do
|
48
|
+
json = '{"test":"hello", "nested":{"foo":"bar"}}'
|
49
|
+
document = Rack::JSON::Document.new(json)
|
50
|
+
assert document.attributes['nested'].is_a?(Hash)
|
51
|
+
assert_equal 'bar', document.attributes['nested']['foo']
|
52
|
+
end
|
53
|
+
|
54
|
+
test "creating from json with multiple nested documents" do
|
55
|
+
json = '{"test":"hello", "nested":[{"foo":"bar"}, {"boo":"far"}]}'
|
56
|
+
document = Rack::JSON::Document.new(json)
|
57
|
+
assert document.attributes['nested'].is_a?(Array)
|
58
|
+
assert_equal({'foo' => 'bar'}, document.attributes['nested'][0])
|
59
|
+
assert_equal 'far', document.attributes['nested'][1]['boo']
|
60
|
+
end
|
61
|
+
|
47
62
|
def test_adding_id
|
48
63
|
json = '{"test":"hello"}'
|
49
64
|
document = Rack::JSON::Document.new(json)
|
data/test/test_filter.rb
CHANGED
@@ -69,4 +69,10 @@ class FilterTest < Test::Unit::TestCase
|
|
69
69
|
post '/testing', '{ "title": "hello!" }'
|
70
70
|
assert_match /"user_id":1/, last_response.body
|
71
71
|
end
|
72
|
+
|
73
|
+
test "handling invalid json" do
|
74
|
+
get '/login'
|
75
|
+
post '/testing', 'invalid json'
|
76
|
+
assert_equal 422, last_response.status
|
77
|
+
end
|
72
78
|
end
|
data/test/test_mongo_document.rb
CHANGED
@@ -3,7 +3,7 @@ require 'helper'
|
|
3
3
|
class MongoDocumentTest < Test::Unit::TestCase
|
4
4
|
|
5
5
|
def test_stringifying_mongo_object_ids
|
6
|
-
hash = {
|
6
|
+
hash = {"_id" => BSON::ObjectID.from_string("4ba7e82ca04014011c000001")}
|
7
7
|
doc = Rack::JSON::MongoDocument.new(hash).attributes
|
8
8
|
assert_equal("4ba7e82ca04014011c000001", doc["_id"])
|
9
9
|
end
|
@@ -11,14 +11,6 @@ class MongoDocumentTest < Test::Unit::TestCase
|
|
11
11
|
def test_not_stringifying_non_mongo_object_ids
|
12
12
|
hash = { "_id" => 1 }
|
13
13
|
doc = Rack::JSON::MongoDocument.new(hash).attributes
|
14
|
-
assert_equal(
|
15
|
-
end
|
16
|
-
|
17
|
-
def test_setting_the_created_at_stamp
|
18
|
-
hash = { "_id" => BSON::ObjectID.from_string("4ba7e82ca04014011c000001") }
|
19
|
-
doc = Rack::JSON::MongoDocument.new(hash).attributes
|
20
|
-
assert_equal({ "_id" => "4ba7e82ca04014011c000001",
|
21
|
-
"created_at" => BSON::ObjectID.from_string("4ba7e82ca04014011c000001").generation_time
|
22
|
-
}, doc)
|
14
|
+
assert_equal(1, doc["_id"])
|
23
15
|
end
|
24
16
|
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class BuilderTest < Test::Unit::TestCase
|
4
|
+
include Rack::Test::Methods
|
5
|
+
include Rack::Utils
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@db = Mongo::Connection.new.db("test")
|
9
|
+
@collection = @db['testing']
|
10
|
+
end
|
11
|
+
|
12
|
+
def teardown
|
13
|
+
@collection.drop
|
14
|
+
end
|
15
|
+
|
16
|
+
def public_resource_app
|
17
|
+
Rack::Builder.app do
|
18
|
+
use Rack::Session::Cookie
|
19
|
+
public_resource :collections => [:testing], :filters => [:user_id], :db => Mongo::Connection.new.db("test")
|
20
|
+
run lambda { |env|
|
21
|
+
# this is doing some pretend login by simply setting a session var
|
22
|
+
request = Rack::JSON::Request.new(env)
|
23
|
+
env['rack.session'] = {}
|
24
|
+
env['rack.session']['user_id'] = 1
|
25
|
+
[200, {'Content-Length' => "6", 'Content-Type' => 'text/plain'}, ["Hello!"]]
|
26
|
+
}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def private_resource_app
|
31
|
+
Rack::Builder.app do
|
32
|
+
use Rack::Session::Cookie
|
33
|
+
private_resource :collections => [:testing], :filters => [:user_id], :db => Mongo::Connection.new.db("test")
|
34
|
+
run lambda { |env|
|
35
|
+
# this is doing some pretend login by simply setting a session var
|
36
|
+
request = Rack::JSON::Request.new(env)
|
37
|
+
env['rack.session'] = {}
|
38
|
+
env['rack.session']['user_id'] = 1
|
39
|
+
[200, {'Content-Length' => "6", 'Content-Type' => 'text/plain'}, ["Hello!"]]
|
40
|
+
}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def expose_resource_app
|
45
|
+
Rack::Builder.app do
|
46
|
+
expose_resource :collections => [:testing], :db => Mongo::Connection.new.db("test")
|
47
|
+
run lambda { |env| [404, {'Content-Length' => '9', 'Content-Type' => 'text/plain'}, ["Not Found"]] }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def use_expose_resource
|
52
|
+
BuilderTest.class_eval { def app; expose_resource_app; end }
|
53
|
+
end
|
54
|
+
|
55
|
+
def use_public_resource
|
56
|
+
BuilderTest.class_eval { def app; public_resource_app; end }
|
57
|
+
end
|
58
|
+
|
59
|
+
def use_private_resource
|
60
|
+
BuilderTest.class_eval { def app; private_resource_app; end }
|
61
|
+
end
|
62
|
+
|
63
|
+
test "using expose_resource we can still bypass rack json" do
|
64
|
+
BuilderTest.class_eval { def app; expose_resource_app; end }
|
65
|
+
|
66
|
+
get '/blah'
|
67
|
+
assert_equal 404, last_response.status
|
68
|
+
end
|
69
|
+
|
70
|
+
test "using expose_resource still gives access to Rack::JSON::Resource" do
|
71
|
+
use_expose_resource
|
72
|
+
|
73
|
+
@collection.save({:testing => true})
|
74
|
+
get '/testing'
|
75
|
+
assert last_response.ok?
|
76
|
+
assert_match /"testing":true/, last_response.body
|
77
|
+
end
|
78
|
+
|
79
|
+
test "using public_resource still can bypass Rack::JSON" do
|
80
|
+
use_public_resource
|
81
|
+
|
82
|
+
get '/blah'
|
83
|
+
assert_equal 200, last_response.status
|
84
|
+
end
|
85
|
+
|
86
|
+
test "using public_resource still gives access to Rack::JSON::Resource" do
|
87
|
+
use_public_resource
|
88
|
+
|
89
|
+
@collection.save({:testing => true})
|
90
|
+
get '/testing'
|
91
|
+
assert last_response.ok?
|
92
|
+
assert_match /"testing":true/, last_response.body
|
93
|
+
end
|
94
|
+
|
95
|
+
test "using public_resource should restrict non get requests to the resources" do
|
96
|
+
use_public_resource
|
97
|
+
|
98
|
+
post '/testing', '{"test":"yes"}'
|
99
|
+
assert_equal 412, last_response.status
|
100
|
+
end
|
101
|
+
|
102
|
+
test "using public resource should not restrict requests when the pre-conditions are met" do
|
103
|
+
use_public_resource
|
104
|
+
|
105
|
+
get '/login' # pretend to login
|
106
|
+
post '/testing', '{"test":"yes"}'
|
107
|
+
assert_equal 201, last_response.status
|
108
|
+
end
|
109
|
+
|
110
|
+
test "using private resource should restrict all requests to the resource" do
|
111
|
+
use_private_resource
|
112
|
+
|
113
|
+
get '/testing'
|
114
|
+
assert_equal 412, last_response.status
|
115
|
+
end
|
116
|
+
|
117
|
+
test "using private resource should not restrict requests when the pre-conditions are met" do
|
118
|
+
use_private_resource
|
119
|
+
|
120
|
+
get '/login' # pretend to login
|
121
|
+
get '/testing'
|
122
|
+
assert last_response.ok?
|
123
|
+
end
|
124
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rackjson
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oliver Nightingale
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-
|
12
|
+
date: 2010-05-06 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -69,6 +69,7 @@ files:
|
|
69
69
|
- Rakefile
|
70
70
|
- VERSION
|
71
71
|
- lib/rackjson.rb
|
72
|
+
- lib/rackjson/base_document.rb
|
72
73
|
- lib/rackjson/collection.rb
|
73
74
|
- lib/rackjson/document.rb
|
74
75
|
- lib/rackjson/end_point.rb
|
@@ -76,6 +77,7 @@ files:
|
|
76
77
|
- lib/rackjson/json_document.rb
|
77
78
|
- lib/rackjson/json_query.rb
|
78
79
|
- lib/rackjson/mongo_document.rb
|
80
|
+
- lib/rackjson/rack/builder.rb
|
79
81
|
- lib/rackjson/request.rb
|
80
82
|
- lib/rackjson/resource.rb
|
81
83
|
- lib/rackjson/response.rb
|
@@ -88,6 +90,7 @@ files:
|
|
88
90
|
- test/test_json_document.rb
|
89
91
|
- test/test_json_query.rb
|
90
92
|
- test/test_mongo_document.rb
|
93
|
+
- test/test_rack_builder.rb
|
91
94
|
- test/test_resource.rb
|
92
95
|
- test/test_response.rb
|
93
96
|
has_rdoc: true
|
@@ -127,5 +130,6 @@ test_files:
|
|
127
130
|
- test/test_json_document.rb
|
128
131
|
- test/test_json_query.rb
|
129
132
|
- test/test_mongo_document.rb
|
133
|
+
- test/test_rack_builder.rb
|
130
134
|
- test/test_resource.rb
|
131
135
|
- test/test_response.rb
|