rack-autocrud 0.1.20 → 0.1.21
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 +15 -0
- data/README.md +11 -6
- data/lib/rack/autocrud.rb +71 -22
- metadata +11 -33
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
MGIxM2M4MTQ4OTg4M2YyNWVhYWQ4ODYxNTE1NTk4NzE5YjljYTVmNg==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
OTY2ODA2ZjNhODU3ZThjNjljYWU3NjgxMzY5NDJlYzNhYjIxNmRhNw==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
NThiMTc2NzU0ZjQ5M2I1OTAwZTY5YmNmN2UxZmI0MjU0NjMzZjkyYWJmY2Rk
|
10
|
+
OGY2NGJjOGNiNWU2ZTE0NTQyOGZiYjNlNWFkZjYxOWFmMWI4NTAxNWFjOTli
|
11
|
+
NGU0ODNmY2UxOGRlMmUzMWE4Nzk3NjcwOWY5ZTg0NGI2YjcwZGQ=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
NTEwZjIyODgyOWIxYjE1OWEzMzg5ODM0MjU3YzliMzY2MzQ2YTU3YjdjNDJh
|
14
|
+
NGE4MDAxNmUyZGRjZDg0ZjIxY2QyNzgyNzJiZDJiMWRlZDI0ZTljNmMwNDE0
|
15
|
+
YzQ3YjQxYjY2OGQyZmFmZTdiZGM4ODc1ZDJhZGE1YjU3YjcyYzQ=
|
data/README.md
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
rack-autocrud
|
2
2
|
=============
|
3
3
|
|
4
|
-
Rack middleware that works with Sinatra
|
5
|
-
|
6
|
-
it works.
|
4
|
+
Rack middleware that works with Sinatra to dynamically create CRUD
|
5
|
+
endpoints and routes based on models. It ain't perfect, but it works.
|
7
6
|
|
8
7
|
These generated CRUD routes are assumed to return a Rack response.
|
9
8
|
|
@@ -12,6 +11,10 @@ modules (read: namespaces).
|
|
12
11
|
|
13
12
|
Input and Response data are formatted as JSON.
|
14
13
|
|
14
|
+
NOTE: While this gem is designed to work with DataMapper, it may be
|
15
|
+
usable with Sequel as well (via ``Sequel::Plugins::JsonSerializer``)
|
16
|
+
since none of the code in ``rack-autocrud`` is DataMapper-dependent.
|
17
|
+
|
15
18
|
Licensing
|
16
19
|
=========
|
17
20
|
|
@@ -21,9 +24,11 @@ Requirements
|
|
21
24
|
============
|
22
25
|
|
23
26
|
* sinatra
|
24
|
-
* datamapper
|
25
27
|
* json
|
26
28
|
|
29
|
+
For DataMapper:
|
30
|
+
* dm-serializer
|
31
|
+
|
27
32
|
Installation
|
28
33
|
============
|
29
34
|
|
@@ -229,8 +234,8 @@ end
|
|
229
234
|
Helper Functions
|
230
235
|
================
|
231
236
|
|
232
|
-
This middleware also adds a helper function to the endpoints, *set_request_body*, to allow
|
233
|
-
you to replace the request body from the aforementioned hooks,
|
237
|
+
This middleware also adds a helper function to the endpoints, *set_request_body*, to allow
|
238
|
+
you to replace the request body from the aforementioned hooks,
|
234
239
|
namely *pre_create* and *pre_update*.
|
235
240
|
|
236
241
|
This function is defined as:
|
data/lib/rack/autocrud.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
#
|
4
4
|
# Copyright (C) 2012 Tim Hentenaar. All Rights Reserved.
|
5
5
|
#
|
6
|
-
# Licensed under the Simplified BSD License.
|
6
|
+
# Licensed under the Simplified BSD License.
|
7
7
|
# See the LICENSE file for details.
|
8
8
|
#
|
9
9
|
# This Rack middleware automatically generates Sinatra
|
@@ -39,38 +39,55 @@ module Rack
|
|
39
39
|
# If this is to '/' pass it on
|
40
40
|
return @app.call(env) if endpoint.nil?
|
41
41
|
|
42
|
-
# Enumerate through all defined classes, checking for the
|
42
|
+
# Enumerate through all defined classes, checking for the
|
43
|
+
# model / endpoint
|
43
44
|
ObjectSpace.each_object(Class) { |klass|
|
44
|
-
|
45
|
-
|
45
|
+
kname = String(klass.name).downcase
|
46
|
+
mname = String(@model_namespace + '::' + endpoint).downcase
|
47
|
+
ename = String(@endpoint_namespace + '::' + endpoint).downcase
|
48
|
+
|
49
|
+
model_klass = klass if kname == mname
|
50
|
+
endpoint_klass = klass if kname == ename
|
46
51
|
}
|
47
52
|
|
48
53
|
# Lazily locate the model namespace module (if we haven't already)
|
49
54
|
if @model_mod.nil?
|
50
55
|
ObjectSpace.each_object(Module) { |klass|
|
51
|
-
|
56
|
+
if String(klass.name).downcase == @model_namespace.downcase
|
57
|
+
@model_mod = klass
|
58
|
+
end
|
52
59
|
}
|
53
60
|
end
|
54
61
|
|
55
|
-
# Lazily locate the endpoint namespace module (if we haven't
|
62
|
+
# Lazily locate the endpoint namespace module (if we haven't
|
63
|
+
# already)
|
56
64
|
if endpoint_klass.nil? && @endpoint_mod.nil?
|
57
65
|
ObjectSpace.each_object(Module) { |klass|
|
58
|
-
|
66
|
+
if String(klass.name).downcase == @endpoint_namespace.downcase
|
67
|
+
@endpoint_mod = klass
|
68
|
+
end
|
59
69
|
}
|
60
70
|
end
|
61
71
|
|
62
72
|
# Make sure we copy the :EXPOSE constant if it's defined upstream
|
63
|
-
if !model_klass.nil? && !model_klass.const_defined?(:EXPOSE) &&
|
73
|
+
if !model_klass.nil? && !model_klass.const_defined?(:EXPOSE) &&
|
74
|
+
@model_mod.const_defined?(:EXPOSE)
|
64
75
|
model_klass.const_set(:EXPOSE,@model_mod.const_get(:EXPOSE))
|
65
76
|
end
|
66
77
|
|
67
|
-
# Make sure we copy the :COLLECTABLE constant if it's defined
|
68
|
-
|
69
|
-
|
78
|
+
# Make sure we copy the :COLLECTABLE constant if it's defined
|
79
|
+
# upstream
|
80
|
+
if !model_klass.nil? && !model_klass.const_defined?(:COLLECTABLE) &&
|
81
|
+
@model_mod.const_defined?(:COLLECTABLE)
|
82
|
+
model_klass.const_set(:COLLECTABLE,
|
83
|
+
@model_mod.const_get(:COLLECTABLE))
|
70
84
|
end
|
71
85
|
|
72
86
|
# Now, if we've got something, do our magic.
|
73
|
-
if !model_klass.nil? && (
|
87
|
+
if !model_klass.nil? && (
|
88
|
+
!model_klass.const_defined?(:EXPOSE) ||
|
89
|
+
model_klass.const_get(:EXPOSE)
|
90
|
+
)
|
74
91
|
# If we don't have an endpoint class, make one
|
75
92
|
if endpoint_klass.nil?
|
76
93
|
endpoint_klass = Class.new(Sinatra::Base)
|
@@ -78,13 +95,17 @@ module Rack
|
|
78
95
|
end
|
79
96
|
|
80
97
|
# Add in any specified helpers
|
81
|
-
@includes.each { |inc|
|
98
|
+
@includes.each { |inc|
|
99
|
+
endpoint_klass.send(:include,inc)
|
100
|
+
} unless @includes.nil?
|
82
101
|
|
83
102
|
# Set any Sinatra options
|
84
|
-
@sinatra_opts.each { |sopt,val|
|
103
|
+
@sinatra_opts.each { |sopt,val|
|
104
|
+
endpoint_klass.send(:set,sopt,val)
|
105
|
+
}
|
85
106
|
|
86
107
|
# Patch in the routes
|
87
|
-
endpoint_klass.class_exec(model_klass,endpoint) { |model,
|
108
|
+
endpoint_klass.class_exec(model_klass,endpoint) { |model,ep|
|
88
109
|
def set_request_body(new_body,content_type='text/json')
|
89
110
|
env['rack.input'] = StringIO.new(new_body)
|
90
111
|
env['CONTENT_LENGTH'] = new_body.length
|
@@ -93,14 +114,22 @@ module Rack
|
|
93
114
|
end
|
94
115
|
|
95
116
|
get '/count' do
|
96
|
-
halt [
|
117
|
+
halt [
|
118
|
+
403,
|
119
|
+
'{ "error": "Access Denied" }'
|
120
|
+
] unless model_klass.const_defined?(:COLLECTABLE) &&
|
121
|
+
model.const_get(:COLLECTABLE)
|
97
122
|
|
98
123
|
# Return the count
|
99
124
|
{ :count => model.all.count }.to_json
|
100
125
|
end
|
101
126
|
|
102
127
|
get '/' do
|
103
|
-
halt [
|
128
|
+
halt [
|
129
|
+
403,
|
130
|
+
'{ "error": "Access Denied" }'
|
131
|
+
] unless model_klass.const_defined?(:COLLECTABLE) &&
|
132
|
+
model.const_get(:COLLECTABLE)
|
104
133
|
|
105
134
|
# Call the pre-create hook
|
106
135
|
if self.respond_to?(:pre_collect)
|
@@ -134,9 +163,18 @@ module Rack
|
|
134
163
|
obj = nil
|
135
164
|
begin
|
136
165
|
obj = model.create(JSON.parse(request.body.read))
|
137
|
-
halt [
|
166
|
+
halt [
|
167
|
+
402,
|
168
|
+
'{ "error": "Failed to save ' + ep + '" }'
|
169
|
+
] unless obj && obj.saved?
|
138
170
|
rescue JSON::ParserError
|
139
|
-
halt [
|
171
|
+
halt [
|
172
|
+
400,
|
173
|
+
{
|
174
|
+
'error' => 'Invalid JSON in request body.',
|
175
|
+
'details' => $!
|
176
|
+
}.to_json
|
177
|
+
]
|
140
178
|
end
|
141
179
|
|
142
180
|
# Call the post-create hook
|
@@ -178,10 +216,18 @@ module Rack
|
|
178
216
|
|
179
217
|
# Attempt to update the model
|
180
218
|
begin
|
181
|
-
saved = model.get(params[:id]).update(
|
219
|
+
saved = model.get(params[:id]).update(
|
220
|
+
JSON.parse(request.body.read)
|
221
|
+
)
|
182
222
|
halt [ 402, '{ "error": "Access Denied" }' ] unless saved
|
183
223
|
rescue JSON::ParserError
|
184
|
-
halt [
|
224
|
+
halt [
|
225
|
+
400,
|
226
|
+
{
|
227
|
+
'error' => 'Invalid JSON in request body.',
|
228
|
+
'details' => $!
|
229
|
+
}.to_json
|
230
|
+
]
|
185
231
|
end
|
186
232
|
|
187
233
|
# Call the post-update hook
|
@@ -201,7 +247,10 @@ module Rack
|
|
201
247
|
end
|
202
248
|
|
203
249
|
obj = model.get(params[:id])
|
204
|
-
return [
|
250
|
+
return [
|
251
|
+
402,
|
252
|
+
'{ "error": "Failed to delete ' + ep + '" }'
|
253
|
+
] unless obj && obj.destroy
|
205
254
|
|
206
255
|
# Call the post-destroy hook
|
207
256
|
if self.respond_to?(:post_destroy)
|
metadata
CHANGED
@@ -1,20 +1,18 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-autocrud
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
5
|
-
prerelease:
|
4
|
+
version: 0.1.21
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Tim Hentenaar
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2014-07-25 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: json
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
17
|
- - ! '>='
|
20
18
|
- !ruby/object:Gem::Version
|
@@ -22,7 +20,6 @@ dependencies:
|
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
24
|
- - ! '>='
|
28
25
|
- !ruby/object:Gem::Version
|
@@ -30,7 +27,6 @@ dependencies:
|
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: sinatra
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
31
|
- - ! '>='
|
36
32
|
- !ruby/object:Gem::Version
|
@@ -38,33 +34,15 @@ dependencies:
|
|
38
34
|
type: :runtime
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
38
|
- - ! '>='
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: '0'
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
- - ! '>='
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: '0'
|
54
|
-
type: :runtime
|
55
|
-
prerelease: false
|
56
|
-
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
|
-
requirements:
|
59
|
-
- - ! '>='
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
62
|
-
description: ! " Rack middleware that works with Sinatra and DataMapper to dynamically\n
|
63
|
-
\ create CRUD endpoints and routes based on models. It ain't perfect, but\n it
|
64
|
-
works.\n\n These generated CRUD routes are assumed to return a Rack response.\n\n
|
65
|
-
\ It's important to note, that you models and endpoints must be in separate\n modules
|
66
|
-
(read: namespaces).\n\n Input and Response data are formatted as JSON.\n\n See
|
67
|
-
the README for more info.\n"
|
41
|
+
description: ! " Rack middleware that works with Sinatra to dynamically create CRUD\n
|
42
|
+
\ endpoints and routes based on models. It ain't perfect, but it works.\n\n These
|
43
|
+
generated CRUD routes are assumed to return a Rack response.\n\n It's important
|
44
|
+
to note, that you models and endpoints must be in\n separate modules (read: namespaces).\n\n
|
45
|
+
\ Input and Response data are formatted as JSON.\n\n See the README for more info.\n"
|
68
46
|
email: tim.hentenaar@gmail.com
|
69
47
|
executables: []
|
70
48
|
extensions: []
|
@@ -75,26 +53,26 @@ files:
|
|
75
53
|
- LICENSE
|
76
54
|
homepage: https://github.com/thentenaar/rack-autocrud
|
77
55
|
licenses: []
|
56
|
+
metadata: {}
|
78
57
|
post_install_message:
|
79
58
|
rdoc_options: []
|
80
59
|
require_paths:
|
81
60
|
- lib
|
82
61
|
required_ruby_version: !ruby/object:Gem::Requirement
|
83
|
-
none: false
|
84
62
|
requirements:
|
85
63
|
- - ! '>='
|
86
64
|
- !ruby/object:Gem::Version
|
87
65
|
version: '0'
|
88
66
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
67
|
requirements:
|
91
68
|
- - ! '>='
|
92
69
|
- !ruby/object:Gem::Version
|
93
70
|
version: '0'
|
94
71
|
requirements: []
|
95
72
|
rubyforge_project:
|
96
|
-
rubygems_version:
|
73
|
+
rubygems_version: 2.0.3
|
97
74
|
signing_key:
|
98
|
-
specification_version:
|
75
|
+
specification_version: 4
|
99
76
|
summary: Rack middleware that automagically handles basic CRUD operations
|
100
77
|
test_files: []
|
78
|
+
has_rdoc:
|