sinatra-rest-json 0.1 → 0.2
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.
- checksums.yaml +4 -4
- data/README.md +23 -5
- data/lib/sinatra/rest_json.rb +47 -2
- data/sinatra-rest-json.gemspec +1 -1
- data/test/test_sinatra_rest_json.rb +68 -1
- metadata +1 -2
- data/lib/sinatra/rest-json.rb +0 -78
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c4081e93189dcd0b6bbc54a6b1ee169c5afc28a3
|
4
|
+
data.tar.gz: 3721f4624f2adb52b8e2ee6d797713bd8b0885f8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f4daf6ec26cc4fed06a496d6f07def6366ad4e25f695d1308ad2c42228681a3647d1ecd575c127cc03c4f9d2634c7d9747e4add7ac16b526df3935507db0b705
|
7
|
+
data.tar.gz: 3c12b6468e34c69cc155483fd9d954a658e22480cb4c1b1976b6fbe3d5f0696683e90f17358901eb1c9047a72f90cfe70f901da1295b5604ebf1007352ad98da
|
data/README.md
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# Easy REST JSON APIs for Sinatra & Active Record
|
2
2
|
|
3
3
|
|
4
|
-
Getting started
|
4
|
+
## Getting started
|
5
5
|
|
6
|
-
|
6
|
+
### 1. Setup your Gemfile
|
7
7
|
|
8
8
|
```ruby
|
9
9
|
# Gemfile
|
@@ -15,7 +15,7 @@ gem "json"
|
|
15
15
|
|
16
16
|
```
|
17
17
|
|
18
|
-
|
18
|
+
### 2. Setup your Sinatra App
|
19
19
|
|
20
20
|
```ruby
|
21
21
|
require 'sinatra'
|
@@ -39,9 +39,9 @@ end
|
|
39
39
|
# Set up your REST routes
|
40
40
|
rest_json Product
|
41
41
|
```
|
42
|
-
|
42
|
+
### 3. Profit
|
43
43
|
|
44
|
-
|
44
|
+
#### Now your app automatically has the following routes which returns JSON data from your model:
|
45
45
|
|
46
46
|
- **GET** /products (all)
|
47
47
|
- **GET** /products/:id (find)
|
@@ -55,3 +55,21 @@ rest_json Product
|
|
55
55
|
*Note for POST/PUT operations the data parameters should be like so: { product: { name: "foo", price: 1 }}
|
56
56
|
|
57
57
|
|
58
|
+
### 4. Authentication
|
59
|
+
|
60
|
+
Basic support for authentication is provided like so:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
# inside your sinatra app
|
64
|
+
|
65
|
+
rest_json Product, :authenticate => {
|
66
|
+
:all => lambda { true }, # allowed
|
67
|
+
:find => lambda { true }, #allowed
|
68
|
+
:create => lambda { false }, #not authorized
|
69
|
+
:update => lambda { false }, #not authorized
|
70
|
+
:delete => lambda { false } #not authorized
|
71
|
+
}
|
72
|
+
```
|
73
|
+
|
74
|
+
You can pass in any ruby object that has a call method which returns a value (e.g. proc or lambda). Naturally you can drop in whatever authentication you'd like
|
75
|
+
|
data/lib/sinatra/rest_json.rb
CHANGED
@@ -6,18 +6,43 @@ module Sinatra
|
|
6
6
|
NOT_FOUND = { :errors => ["record doesn't exist"] }.to_json
|
7
7
|
MODEL_REGEX = /([A-Z0-9]{1}[a-z0-9]+)/
|
8
8
|
|
9
|
+
NO_AUTH = lambda { true }
|
10
|
+
DEFAULT_AUTH = {
|
11
|
+
:all => NO_AUTH,
|
12
|
+
:find => NO_AUTH,
|
13
|
+
:create => NO_AUTH,
|
14
|
+
:update => NO_AUTH,
|
15
|
+
:delete => NO_AUTH
|
16
|
+
}
|
17
|
+
|
9
18
|
def rest_json(model_class, opts = {})
|
10
19
|
model_name = model_class.name.scan(MODEL_REGEX).join("_").downcase
|
11
20
|
route_name = model_class.table_name
|
12
21
|
|
22
|
+
options = opts.clone
|
23
|
+
options[:authenticate] ||= {}
|
24
|
+
authenticate = DEFAULT_AUTH.merge(options[:authenticate])
|
25
|
+
|
13
26
|
# all
|
14
27
|
get "/#{route_name}" do
|
28
|
+
authorized = authenticate[:all].call
|
29
|
+
|
30
|
+
unless authorized
|
31
|
+
halt 401, "Not authorized\n"
|
32
|
+
end
|
33
|
+
|
15
34
|
content_type :json
|
16
35
|
"[" + model_class.all.collect { |m| m.to_json }.join(",") + "]"
|
17
36
|
end
|
18
37
|
|
19
38
|
# find
|
20
39
|
get "/#{route_name}/:id" do
|
40
|
+
authorized = authenticate[:find].call
|
41
|
+
|
42
|
+
unless authorized
|
43
|
+
halt 401, "Not authorized\n"
|
44
|
+
end
|
45
|
+
|
21
46
|
content_type :json
|
22
47
|
model = model_class.find(params[:id].to_i)
|
23
48
|
|
@@ -29,7 +54,13 @@ module Sinatra
|
|
29
54
|
end
|
30
55
|
|
31
56
|
# create
|
32
|
-
|
57
|
+
post "/#{route_name}" do
|
58
|
+
authorized = authenticate[:create].call
|
59
|
+
|
60
|
+
unless authorized
|
61
|
+
halt 401, "Not authorized\n"
|
62
|
+
end
|
63
|
+
|
33
64
|
content_type :json
|
34
65
|
|
35
66
|
model = model_class.new(params[model_name])
|
@@ -42,7 +73,13 @@ module Sinatra
|
|
42
73
|
end
|
43
74
|
|
44
75
|
# update
|
45
|
-
|
76
|
+
put "/#{route_name}/:id" do
|
77
|
+
authorized = authenticate[:update].call
|
78
|
+
|
79
|
+
unless authorized
|
80
|
+
halt 401, "Not authorized\n"
|
81
|
+
end
|
82
|
+
|
46
83
|
content_type :json
|
47
84
|
|
48
85
|
model = model_class.find(params[:id].to_i)
|
@@ -60,6 +97,13 @@ module Sinatra
|
|
60
97
|
|
61
98
|
# delete
|
62
99
|
delete "/#{route_name}/:id" do
|
100
|
+
|
101
|
+
authorized = authenticate[:delete].call
|
102
|
+
|
103
|
+
unless authorized
|
104
|
+
halt 401, "Not authorized\n"
|
105
|
+
end
|
106
|
+
|
63
107
|
content_type :json
|
64
108
|
|
65
109
|
model = model_class.find(params[:id].to_i)
|
@@ -74,5 +118,6 @@ module Sinatra
|
|
74
118
|
|
75
119
|
end
|
76
120
|
|
121
|
+
|
77
122
|
register REST
|
78
123
|
end
|
data/sinatra-rest-json.gemspec
CHANGED
@@ -4,7 +4,7 @@ require 'rack/test'
|
|
4
4
|
require "minitest/autorun"
|
5
5
|
|
6
6
|
require 'sinatra/base'
|
7
|
-
require 'sinatra/
|
7
|
+
require 'sinatra/rest_json'
|
8
8
|
require 'json'
|
9
9
|
|
10
10
|
require File.join(File.dirname(__FILE__), "helper")
|
@@ -15,6 +15,7 @@ class TestApp < Sinatra::Base
|
|
15
15
|
end
|
16
16
|
|
17
17
|
|
18
|
+
|
18
19
|
describe "app" do
|
19
20
|
include Rack::Test::Methods
|
20
21
|
|
@@ -103,5 +104,71 @@ describe "app" do
|
|
103
104
|
assert_equal FooModel.all.size, 0
|
104
105
|
end
|
105
106
|
end
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
class AuthenticatedTestApp < Sinatra::Base
|
111
|
+
register Sinatra::REST
|
112
|
+
rest_json FooModel, :authenticate => {
|
113
|
+
:all => lambda { true },
|
114
|
+
:find => lambda { true },
|
115
|
+
:create => lambda { false },
|
116
|
+
:update => lambda { false },
|
117
|
+
:delete => lambda { false }
|
118
|
+
}
|
119
|
+
end
|
120
|
+
|
121
|
+
describe "authenticated app" do
|
122
|
+
include Rack::Test::Methods
|
123
|
+
|
124
|
+
def app
|
125
|
+
AuthenticatedTestApp
|
126
|
+
end
|
127
|
+
|
128
|
+
before do
|
129
|
+
FooModel.destroy_all
|
130
|
+
end
|
131
|
+
|
132
|
+
|
133
|
+
describe "GET /" do
|
134
|
+
it "should allow all when data" do
|
135
|
+
FooModel.create(:name => "foo1")
|
136
|
+
|
137
|
+
get "/foo_models"
|
138
|
+
assert_equal last_response.status, 200
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
describe "GET /foo_models/:id" do
|
143
|
+
it "should allow finding a model" do
|
144
|
+
FooModel.create(:name => "foo1")
|
145
|
+
get "/foo_models/1"
|
146
|
+
assert_equal last_response.status, 200
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
describe "POST /foo_models" do
|
151
|
+
it "should not allow creation" do
|
152
|
+
assert_equal FooModel.all.size, 0
|
153
|
+
post "/foo_models", { :foo_model => { :name => "foo1" } }
|
154
|
+
assert_equal last_response.status, 401
|
155
|
+
end
|
156
|
+
end
|
106
157
|
|
158
|
+
|
159
|
+
describe "PUT /foo_models/:id" do
|
160
|
+
it "should not allow updating" do
|
161
|
+
FooModel.create(:name => "foo1")
|
162
|
+
put "/foo_models/1", { :foo_model => { :name => "boo" } }
|
163
|
+
assert_equal last_response.status, 401
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
describe "DELETE /foo_models/:id" do
|
168
|
+
it "should now allow deletion" do
|
169
|
+
FooModel.create(:name => "foo1")
|
170
|
+
delete "/foo_models/1"
|
171
|
+
assert_equal last_response.status, 401
|
172
|
+
end
|
173
|
+
end
|
107
174
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sinatra-rest-json
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.2'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joshua Carver
|
@@ -49,7 +49,6 @@ files:
|
|
49
49
|
- LICENSE
|
50
50
|
- README.md
|
51
51
|
- Rakefile
|
52
|
-
- lib/sinatra/rest-json.rb
|
53
52
|
- lib/sinatra/rest_json.rb
|
54
53
|
- sinatra-rest-json.gemspec
|
55
54
|
- test/helper.rb
|
data/lib/sinatra/rest-json.rb
DELETED
@@ -1,78 +0,0 @@
|
|
1
|
-
require 'sinatra/base'
|
2
|
-
require 'json'
|
3
|
-
|
4
|
-
module Sinatra
|
5
|
-
module REST
|
6
|
-
NOT_FOUND = { :errors => ["record doesn't exist"] }.to_json
|
7
|
-
MODEL_REGEX = /([A-Z0-9]{1}[a-z0-9]+)/
|
8
|
-
|
9
|
-
def rest_json(model_class, opts = {})
|
10
|
-
model_name = model_class.name.scan(MODEL_REGEX).join("_").downcase
|
11
|
-
route_name = model_class.table_name
|
12
|
-
|
13
|
-
# all
|
14
|
-
get "/#{route_name}" do
|
15
|
-
content_type :json
|
16
|
-
"[" + model_class.all.collect { |m| m.to_json }.join(",") + "]"
|
17
|
-
end
|
18
|
-
|
19
|
-
# find
|
20
|
-
get "/#{route_name}/:id" do
|
21
|
-
content_type :json
|
22
|
-
model = model_class.find(params[:id].to_i)
|
23
|
-
|
24
|
-
if model.nil?
|
25
|
-
NOT_FOUND
|
26
|
-
else
|
27
|
-
model.to_json
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
# create
|
32
|
-
post "/#{route_name}" do
|
33
|
-
content_type :json
|
34
|
-
|
35
|
-
model = model_class.new(params[model_name])
|
36
|
-
|
37
|
-
if model.save
|
38
|
-
model.to_json
|
39
|
-
else
|
40
|
-
{ :errors => model.errors }.to_json
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
# update
|
45
|
-
put "/#{route_name}/:id" do
|
46
|
-
content_type :json
|
47
|
-
|
48
|
-
model = model_class.find(params[:id].to_i)
|
49
|
-
|
50
|
-
if model.nil?
|
51
|
-
NOT_FOUND
|
52
|
-
else
|
53
|
-
if model.update_attributes(params[model_name])
|
54
|
-
model.to_json
|
55
|
-
else
|
56
|
-
{ :errors => model.errors }.to_json
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
# delete
|
62
|
-
delete "/#{route_name}/:id" do
|
63
|
-
content_type :json
|
64
|
-
|
65
|
-
model = model_class.find(params[:id].to_i)
|
66
|
-
|
67
|
-
if model.nil?
|
68
|
-
NOT_FOUND
|
69
|
-
else
|
70
|
-
model.destroy.to_json
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
end
|
76
|
-
|
77
|
-
register REST
|
78
|
-
end
|