djsun-rest-sinatra 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/.document +5 -0
- data/.gitignore +5 -0
- data/Rakefile +48 -0
- data/VERSION +1 -0
- data/lib/rest-sinatra.rb +280 -0
- data/spec/helpers/comments.rb +18 -0
- data/spec/helpers/posts.rb +22 -0
- data/spec/helpers/sinatra_stubs.rb +39 -0
- data/spec/helpers/sources.rb +12 -0
- data/spec/helpers/spec_helper.rb +3 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/unit/posts_and_comments_spec.rb +148 -0
- data/spec/unit/sources_spec.rb +94 -0
- metadata +40 -13
- data/rakefile.rb +0 -24
data/.document
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "rest-sinatra"
|
8
|
+
gem.summary = %Q{Easily write RESTful actions with Sinatra and MongoMapper}
|
9
|
+
gem.description = %Q{Provides a DSL for making RESTful Sinatra actions with MongoMapper models.}
|
10
|
+
gem.email = "djames@sunlightfoundation.com"
|
11
|
+
gem.homepage = "http://github.com/djsun/rest-sinatra"
|
12
|
+
gem.authors = ["David James"]
|
13
|
+
gem.add_development_dependency "rspec"
|
14
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
15
|
+
end
|
16
|
+
rescue LoadError
|
17
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'spec/rake/spectask'
|
21
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
22
|
+
spec.libs << 'lib' << 'spec'
|
23
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
24
|
+
end
|
25
|
+
|
26
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
27
|
+
spec.libs << 'lib' << 'spec'
|
28
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
29
|
+
spec.rcov = true
|
30
|
+
end
|
31
|
+
|
32
|
+
task :spec => :check_dependencies
|
33
|
+
|
34
|
+
task :default => :spec
|
35
|
+
|
36
|
+
require 'rake/rdoctask'
|
37
|
+
Rake::RDocTask.new do |rdoc|
|
38
|
+
if File.exist?('VERSION')
|
39
|
+
version = File.read('VERSION')
|
40
|
+
else
|
41
|
+
version = ""
|
42
|
+
end
|
43
|
+
|
44
|
+
rdoc.rdoc_dir = 'rdoc'
|
45
|
+
rdoc.title = "rest-sinatra #{version}"
|
46
|
+
rdoc.rdoc_files.include('README*')
|
47
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
48
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.3.0
|
data/lib/rest-sinatra.rb
ADDED
@@ -0,0 +1,280 @@
|
|
1
|
+
module RestSinatra
|
2
|
+
|
3
|
+
def self.included(includer)
|
4
|
+
includer.extend(ClassMethods)
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
|
9
|
+
attr_reader :config
|
10
|
+
|
11
|
+
def resource(name, &block)
|
12
|
+
_resource(name, :regular, &block)
|
13
|
+
end
|
14
|
+
|
15
|
+
def nestable_resource(name, &block)
|
16
|
+
_resource(name, :nestable, &block)
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def _resource(name, resource_type, &block)
|
22
|
+
config = evaluate_block(name, resource_type, &block)
|
23
|
+
validate(config)
|
24
|
+
build_resource(config)
|
25
|
+
config
|
26
|
+
end
|
27
|
+
|
28
|
+
def evaluate_block(name, resource_type, &block)
|
29
|
+
scope = Object.new
|
30
|
+
scope.extend(ResourceMethods)
|
31
|
+
scope.instance_eval do
|
32
|
+
@c = {
|
33
|
+
:name => name,
|
34
|
+
:resource_type => resource_type,
|
35
|
+
:model => nil,
|
36
|
+
:read_only => [],
|
37
|
+
:permission => nil,
|
38
|
+
:callbacks => {},
|
39
|
+
:nested_resources => []
|
40
|
+
}
|
41
|
+
end
|
42
|
+
scope.instance_eval(&block)
|
43
|
+
scope.instance_variable_get("@c")
|
44
|
+
end
|
45
|
+
|
46
|
+
def validate(c)
|
47
|
+
raise "name required" unless c[:name]
|
48
|
+
raise "model required" unless c[:model]
|
49
|
+
c[:nested_resources].each do |resource|
|
50
|
+
unless resource[:association]
|
51
|
+
raise "association required for #{resource[:class]}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def build_resource(config)
|
57
|
+
case config[:resource_type]
|
58
|
+
when :regular
|
59
|
+
build_parent_resource(config)
|
60
|
+
build_nested_resources(config)
|
61
|
+
when :nestable
|
62
|
+
save_nestable_config(config)
|
63
|
+
else
|
64
|
+
raise "Unexpected resource_type"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def build_parent_resource(config)
|
69
|
+
callbacks = config[:callbacks]
|
70
|
+
model = config[:model]
|
71
|
+
name = config[:name]
|
72
|
+
read_only = config[:read_only]
|
73
|
+
|
74
|
+
get '/?' do
|
75
|
+
require_at_least(:basic)
|
76
|
+
@documents = find(params, model)
|
77
|
+
@documents.to_json
|
78
|
+
end
|
79
|
+
|
80
|
+
get '/:id/?' do |id|
|
81
|
+
require_at_least(:basic)
|
82
|
+
id = params.delete("id")
|
83
|
+
@document = model.find_by_id(id)
|
84
|
+
error 404, [].to_json unless @document
|
85
|
+
@document.to_json
|
86
|
+
end
|
87
|
+
|
88
|
+
post '/?' do
|
89
|
+
require_at_least(:curator)
|
90
|
+
id = params.delete("id")
|
91
|
+
validate_before_create(params, model, read_only)
|
92
|
+
@document = model.find_by_id(id)
|
93
|
+
callback callbacks[:before_save]
|
94
|
+
callback callbacks[:before_create]
|
95
|
+
@document = model.new(params)
|
96
|
+
unless @document.valid?
|
97
|
+
error 400, { "errors" => @document.errors.errors }.to_json
|
98
|
+
end
|
99
|
+
@document.save
|
100
|
+
callback callbacks[:after_create]
|
101
|
+
callback callbacks[:after_save]
|
102
|
+
response.status = 201
|
103
|
+
response.headers['Location'] = full_uri "/#{name}/#{@document.id}"
|
104
|
+
@document.to_json
|
105
|
+
end
|
106
|
+
|
107
|
+
put '/:id/?' do
|
108
|
+
require_at_least(:curator)
|
109
|
+
id = params.delete("id")
|
110
|
+
@document = model.find_by_id(id)
|
111
|
+
error 404, [].to_json unless @document
|
112
|
+
validate_before_update(params, model, read_only)
|
113
|
+
callback(callbacks[:before_save])
|
114
|
+
callback(callbacks[:before_update])
|
115
|
+
validate_before_update(params, model, read_only)
|
116
|
+
@document = model.update(id, params)
|
117
|
+
unless @document.valid?
|
118
|
+
error 400, { "errors" => @document.errors.errors }.to_json
|
119
|
+
end
|
120
|
+
callback(callbacks[:after_update])
|
121
|
+
callback(callbacks[:after_save])
|
122
|
+
@document.to_json
|
123
|
+
end
|
124
|
+
|
125
|
+
delete '/:id/?' do
|
126
|
+
require_at_least(:curator)
|
127
|
+
id = params.delete("id")
|
128
|
+
@document = model.find_by_id(id)
|
129
|
+
error 404, [].to_json unless @document
|
130
|
+
callback(callbacks[:before_destroy])
|
131
|
+
@document.destroy
|
132
|
+
callback(callbacks[:after_destroy])
|
133
|
+
{ "id" => id }.to_json
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def build_nested_resources(parent_config)
|
138
|
+
parent_config[:nested_resources].each do |resource|
|
139
|
+
nested_res_class = resource[:class]
|
140
|
+
assoc = resource[:association]
|
141
|
+
nested_config = restore_nestable_config(nested_res_class)
|
142
|
+
build_nested_resource(nested_res_class, assoc, parent_config, nested_config)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# klass : nested resource class
|
147
|
+
# association : a method on the parent model that will return child models
|
148
|
+
def build_nested_resource(klass, association, parent_config, child_config)
|
149
|
+
callbacks = child_config[:callbacks]
|
150
|
+
child_model = child_config[:model]
|
151
|
+
child_name = child_config[:name]
|
152
|
+
permission = child_config[:permission]
|
153
|
+
read_only = child_config[:read_only]
|
154
|
+
|
155
|
+
parent_model = parent_config[:model]
|
156
|
+
parent_name = parent_config[:name]
|
157
|
+
|
158
|
+
get "/:parent_id/#{child_name}/?" do
|
159
|
+
parent_id = params.delete("parent_id")
|
160
|
+
permission_check(:basic, permission, parent_id)
|
161
|
+
@parent_document = find_parent(parent_model, parent_id)
|
162
|
+
all_child_documents = @parent_document.send(association)
|
163
|
+
@child_documents = nested_find(all_child_documents, params, parent_model)
|
164
|
+
@child_documents.to_json
|
165
|
+
end
|
166
|
+
|
167
|
+
get "/:parent_id/#{child_name}/:child_id/?" do
|
168
|
+
parent_id = params.delete("parent_id")
|
169
|
+
permission_check(:basic, permission, parent_id)
|
170
|
+
child_id = params.delete("child_id")
|
171
|
+
@parent_document, @child_document = find_documents(parent_model, parent_id, association, child_id)
|
172
|
+
@child_document.to_json
|
173
|
+
end
|
174
|
+
|
175
|
+
post "/:parent_id/#{child_name}/?" do
|
176
|
+
parent_id = params.delete("parent_id")
|
177
|
+
permission_check(:curator, permission, parent_id)
|
178
|
+
@parent_document = find_parent(parent_model, parent_id)
|
179
|
+
validate_before_create(params, child_model, read_only)
|
180
|
+
callback callbacks[:before_save]
|
181
|
+
callback callbacks[:before_create]
|
182
|
+
@child_document = child_model.new(params)
|
183
|
+
@parent_document.send(association) << @child_document
|
184
|
+
error 500, [].to_json unless @parent_document.save
|
185
|
+
callback callbacks[:after_create]
|
186
|
+
callback callbacks[:after_save]
|
187
|
+
response.status = 201
|
188
|
+
response.headers['Location'] = full_uri(
|
189
|
+
"/#{parent_name}/#{parent_id}/#{child_name}/#{@child_document.id}"
|
190
|
+
)
|
191
|
+
@child_document.to_json
|
192
|
+
end
|
193
|
+
|
194
|
+
put "/:parent_id/#{child_name}/:child_id/?" do
|
195
|
+
parent_id = params.delete("parent_id")
|
196
|
+
permission_check(:curator, permission, parent_id)
|
197
|
+
child_id = params.delete("child_id")
|
198
|
+
@parent_document, @child_document = find_documents(parent_model, parent_id, association, child_id)
|
199
|
+
validate_before_update(params, child_model, read_only)
|
200
|
+
callback callbacks[:before_save]
|
201
|
+
callback callbacks[:before_update]
|
202
|
+
@child_document.attributes = params
|
203
|
+
child_index = @parent_document.send(association).index(@child_document)
|
204
|
+
@parent_document.send(association)[child_index] = @child_document
|
205
|
+
error 500, [].to_json unless @parent_document.save
|
206
|
+
callback callbacks[:after_update]
|
207
|
+
callback callbacks[:after_save]
|
208
|
+
@child_document.to_json
|
209
|
+
end
|
210
|
+
|
211
|
+
delete "/:parent_id/#{child_name}/:child_id/?" do
|
212
|
+
parent_id = params.delete("parent_id")
|
213
|
+
permission_check(:curator, permission, parent_id)
|
214
|
+
child_id = params.delete("child_id")
|
215
|
+
@parent_document, @child_document = find_documents(parent_model, parent_id, association, child_id)
|
216
|
+
callback callbacks[:before_destroy]
|
217
|
+
@parent_document.send(association).delete(@child_document)
|
218
|
+
callback callbacks[:after_destroy]
|
219
|
+
error 500, [].to_json unless @parent_document.save
|
220
|
+
{ "id" => child_id }.to_json
|
221
|
+
end
|
222
|
+
|
223
|
+
helpers do
|
224
|
+
def find_parent(parent_model, parent_id)
|
225
|
+
parent_document = parent_model.find_by_id(parent_id)
|
226
|
+
error 404, [].to_json unless parent_document
|
227
|
+
parent_document
|
228
|
+
end
|
229
|
+
|
230
|
+
def find_child(parent_document, association, child_id)
|
231
|
+
child_document = parent_document.send(association).find { |x| x.id == child_id }
|
232
|
+
error 404, [].to_json unless child_document
|
233
|
+
child_document
|
234
|
+
end
|
235
|
+
|
236
|
+
def find_documents(parent_model, parent_id, association, child_id)
|
237
|
+
parent_document = find_parent(parent_model, parent_id)
|
238
|
+
child_document = find_child(parent_document, association, child_id)
|
239
|
+
[parent_document, child_document]
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
def save_nestable_config(config)
|
245
|
+
@nestable_resource_config = config
|
246
|
+
end
|
247
|
+
|
248
|
+
def restore_nestable_config(klass)
|
249
|
+
klass.instance_variable_get("@nestable_resource_config")
|
250
|
+
end
|
251
|
+
|
252
|
+
end
|
253
|
+
|
254
|
+
module ResourceMethods
|
255
|
+
|
256
|
+
def model(model)
|
257
|
+
raise "model already declared" if @c[:model]
|
258
|
+
@c[:model] = model
|
259
|
+
end
|
260
|
+
|
261
|
+
def read_only(attribute)
|
262
|
+
@c[:read_only] << attribute
|
263
|
+
end
|
264
|
+
|
265
|
+
def permission(level)
|
266
|
+
raise "permission already declared" if @c[:permission]
|
267
|
+
@c[:permission] = level
|
268
|
+
end
|
269
|
+
|
270
|
+
def callback(name, &block)
|
271
|
+
@c[:callbacks][name] = block
|
272
|
+
end
|
273
|
+
|
274
|
+
def nested_resource(klass, options)
|
275
|
+
@c[:nested_resources] << options.merge({:class => klass})
|
276
|
+
end
|
277
|
+
|
278
|
+
end
|
279
|
+
|
280
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/sinatra_stubs')
|
2
|
+
|
3
|
+
class Comment ; end
|
4
|
+
|
5
|
+
class Comments
|
6
|
+
include RestSinatra
|
7
|
+
include SinatraStubs
|
8
|
+
|
9
|
+
@r = nestable_resource "comments" do
|
10
|
+
model Comment
|
11
|
+
|
12
|
+
read_only :created_at
|
13
|
+
|
14
|
+
callback :before_save do
|
15
|
+
"before saving comments"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/sinatra_stubs')
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/comments')
|
3
|
+
|
4
|
+
class Post ; end
|
5
|
+
|
6
|
+
class Posts
|
7
|
+
include RestSinatra
|
8
|
+
include SinatraStubs
|
9
|
+
|
10
|
+
@r = resource "posts" do
|
11
|
+
model Post
|
12
|
+
|
13
|
+
read_only :created_at
|
14
|
+
read_only :updated_at
|
15
|
+
|
16
|
+
nested_resource Comments, :association => :comments
|
17
|
+
|
18
|
+
callback :before_save do
|
19
|
+
"before saving posts"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module SinatraStubs
|
2
|
+
|
3
|
+
def self.included(includer)
|
4
|
+
includer.class_eval do
|
5
|
+
@actions = {
|
6
|
+
:get => [],
|
7
|
+
:post => [],
|
8
|
+
:put => [],
|
9
|
+
:delete => []
|
10
|
+
}
|
11
|
+
end
|
12
|
+
includer.extend(ClassMethods)
|
13
|
+
end
|
14
|
+
|
15
|
+
module ClassMethods
|
16
|
+
attr_reader :actions
|
17
|
+
|
18
|
+
def get(route)
|
19
|
+
@actions[:get] << route
|
20
|
+
end
|
21
|
+
|
22
|
+
def post(route)
|
23
|
+
@actions[:post] << route
|
24
|
+
end
|
25
|
+
|
26
|
+
def put(route)
|
27
|
+
@actions[:put] << route
|
28
|
+
end
|
29
|
+
|
30
|
+
def delete(route)
|
31
|
+
@actions[:delete] << route
|
32
|
+
end
|
33
|
+
|
34
|
+
def helpers()
|
35
|
+
# ...
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../helpers/spec_helper.rb')
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/../helpers/posts.rb')
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/../helpers/comments.rb')
|
4
|
+
|
5
|
+
describe "Posts" do
|
6
|
+
|
7
|
+
before do
|
8
|
+
@config = Posts.instance_variable_get("@r")
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "DSL methods" do
|
12
|
+
it "resource should be 'posts'" do
|
13
|
+
@config[:name].should == "posts"
|
14
|
+
end
|
15
|
+
|
16
|
+
it "model should be Post" do
|
17
|
+
@config[:model].should == Post
|
18
|
+
end
|
19
|
+
|
20
|
+
it "read_only should be correct" do
|
21
|
+
@config[:read_only].should == [:created_at, :updated_at]
|
22
|
+
end
|
23
|
+
|
24
|
+
it "callback :before_create should be correct" do
|
25
|
+
@config[:callbacks][:before_save].call.should == "before saving posts"
|
26
|
+
end
|
27
|
+
|
28
|
+
it "callback :before_update should return nil" do
|
29
|
+
@config[:callbacks][:before_update].should == nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "actions" do
|
34
|
+
before do
|
35
|
+
@actions = Posts.actions
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "get" do
|
39
|
+
before do
|
40
|
+
@acts = @actions[:get]
|
41
|
+
end
|
42
|
+
|
43
|
+
it "get /?" do
|
44
|
+
@acts.should include("/?")
|
45
|
+
end
|
46
|
+
|
47
|
+
it "get /:id/?" do
|
48
|
+
@acts.should include("/:id/?")
|
49
|
+
end
|
50
|
+
|
51
|
+
it "get /:parent_id/comments/?" do
|
52
|
+
@acts.should include("/:parent_id/comments/?")
|
53
|
+
end
|
54
|
+
|
55
|
+
it "get /:parent_id/comments/:child_id/?" do
|
56
|
+
@acts.should include("/:parent_id/comments/:child_id/?")
|
57
|
+
end
|
58
|
+
|
59
|
+
it "exactly 4 actions" do
|
60
|
+
@acts.length.should == 4
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "post" do
|
65
|
+
before do
|
66
|
+
@acts = @actions[:post]
|
67
|
+
end
|
68
|
+
|
69
|
+
it "post /?" do
|
70
|
+
@acts.should include("/?")
|
71
|
+
end
|
72
|
+
|
73
|
+
it "post /:parent_id/comments/?" do
|
74
|
+
@acts.should include("/:parent_id/comments/?")
|
75
|
+
end
|
76
|
+
|
77
|
+
it "exactly 2 actions" do
|
78
|
+
@acts.length.should == 2
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "put" do
|
83
|
+
before do
|
84
|
+
@acts = @actions[:put]
|
85
|
+
end
|
86
|
+
|
87
|
+
it "put /:id/?" do
|
88
|
+
@acts.should include("/:id/?")
|
89
|
+
end
|
90
|
+
|
91
|
+
it "put /:parent_id/comments/:child_id/?" do
|
92
|
+
@acts.should include("/:parent_id/comments/:child_id/?")
|
93
|
+
end
|
94
|
+
|
95
|
+
it "exactly 2 actions" do
|
96
|
+
@acts.length.should == 2
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "delete" do
|
101
|
+
before do
|
102
|
+
@acts = @actions[:delete]
|
103
|
+
end
|
104
|
+
|
105
|
+
it "delete /:id/?" do
|
106
|
+
@acts.should include("/:id/?")
|
107
|
+
end
|
108
|
+
|
109
|
+
it "delete /:parent_id/comments/:child_id/?" do
|
110
|
+
@acts.should include("/:parent_id/comments/:child_id/?")
|
111
|
+
end
|
112
|
+
|
113
|
+
it "exactly 2 actions" do
|
114
|
+
@acts.length.should == 2
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
describe "Comments" do
|
122
|
+
|
123
|
+
before do
|
124
|
+
@config = Comments.instance_variable_get("@r")
|
125
|
+
end
|
126
|
+
|
127
|
+
describe "DSL methods" do
|
128
|
+
it "resource should be 'comments'" do
|
129
|
+
@config[:name].should == "comments"
|
130
|
+
end
|
131
|
+
|
132
|
+
it "model should be Comment" do
|
133
|
+
@config[:model].should == Comment
|
134
|
+
end
|
135
|
+
|
136
|
+
it "read_only should be correct" do
|
137
|
+
@config[:read_only].should == [:created_at]
|
138
|
+
end
|
139
|
+
|
140
|
+
it "callback :before_create should be correct" do
|
141
|
+
@config[:callbacks][:before_save].call.should == "before saving comments"
|
142
|
+
end
|
143
|
+
|
144
|
+
it "callback :before_update should return nil" do
|
145
|
+
@config[:callbacks][:before_update].should == nil
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../helpers/spec_helper')
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/../helpers/sources')
|
3
|
+
|
4
|
+
describe "Sources" do
|
5
|
+
|
6
|
+
describe "DSL methods" do
|
7
|
+
before do
|
8
|
+
@config = Sources.instance_variable_get("@r")
|
9
|
+
end
|
10
|
+
|
11
|
+
it "name should be 'sources'" do
|
12
|
+
@config[:name].should == "sources"
|
13
|
+
end
|
14
|
+
|
15
|
+
it "model should be Source" do
|
16
|
+
@config[:model].should == Source
|
17
|
+
end
|
18
|
+
|
19
|
+
it "read_only should be empty" do
|
20
|
+
@config[:read_only].should == []
|
21
|
+
end
|
22
|
+
|
23
|
+
it "callbacks should be empty" do
|
24
|
+
@config[:callbacks].should == {}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "actions" do
|
29
|
+
before do
|
30
|
+
@actions = Sources.actions
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "get" do
|
34
|
+
before do
|
35
|
+
@acts = @actions[:get]
|
36
|
+
end
|
37
|
+
|
38
|
+
it "get /?" do
|
39
|
+
@acts.should include("/?")
|
40
|
+
end
|
41
|
+
|
42
|
+
it "get /:id/?" do
|
43
|
+
@acts.should include("/:id/?")
|
44
|
+
end
|
45
|
+
|
46
|
+
it "exactly 2 actions" do
|
47
|
+
@acts.length.should == 2
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "post" do
|
52
|
+
before do
|
53
|
+
@acts = @actions[:post]
|
54
|
+
end
|
55
|
+
|
56
|
+
it "post /?" do
|
57
|
+
@acts.should include("/?")
|
58
|
+
end
|
59
|
+
|
60
|
+
it "exactly 1 action" do
|
61
|
+
@acts.length.should == 1
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "put" do
|
66
|
+
before do
|
67
|
+
@acts = @actions[:put]
|
68
|
+
end
|
69
|
+
|
70
|
+
it "put /:id/?" do
|
71
|
+
@acts.should include("/:id/?")
|
72
|
+
end
|
73
|
+
|
74
|
+
it "exactly 1 action" do
|
75
|
+
@acts.length.should == 1
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "delete" do
|
80
|
+
before do
|
81
|
+
@acts = @actions[:delete]
|
82
|
+
end
|
83
|
+
|
84
|
+
it "delete /:id/?" do
|
85
|
+
@acts.should include("/:id/?")
|
86
|
+
end
|
87
|
+
|
88
|
+
it "exactly 1 action" do
|
89
|
+
@acts.length.should == 1
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: djsun-rest-sinatra
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David James
|
@@ -11,11 +11,19 @@ cert_chain: []
|
|
11
11
|
|
12
12
|
date: 2009-09-24 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
|
-
dependencies:
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rspec
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
description: Provides a DSL for making RESTful Sinatra actions with MongoMapper models.
|
26
|
+
email: djames@sunlightfoundation.com
|
19
27
|
executables: []
|
20
28
|
|
21
29
|
extensions: []
|
@@ -24,10 +32,22 @@ extra_rdoc_files:
|
|
24
32
|
- LICENSE
|
25
33
|
- README.md
|
26
34
|
files:
|
35
|
+
- .document
|
36
|
+
- .gitignore
|
27
37
|
- LICENSE
|
28
|
-
- rakefile.rb
|
29
38
|
- README.md
|
30
|
-
|
39
|
+
- Rakefile
|
40
|
+
- VERSION
|
41
|
+
- lib/rest-sinatra.rb
|
42
|
+
- spec/helpers/comments.rb
|
43
|
+
- spec/helpers/posts.rb
|
44
|
+
- spec/helpers/sinatra_stubs.rb
|
45
|
+
- spec/helpers/sources.rb
|
46
|
+
- spec/helpers/spec_helper.rb
|
47
|
+
- spec/spec_helper.rb
|
48
|
+
- spec/unit/posts_and_comments_spec.rb
|
49
|
+
- spec/unit/sources_spec.rb
|
50
|
+
has_rdoc: false
|
31
51
|
homepage: http://github.com/djsun/rest-sinatra
|
32
52
|
licenses:
|
33
53
|
post_install_message:
|
@@ -49,10 +69,17 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
49
69
|
version:
|
50
70
|
requirements: []
|
51
71
|
|
52
|
-
rubyforge_project:
|
72
|
+
rubyforge_project:
|
53
73
|
rubygems_version: 1.3.5
|
54
74
|
signing_key:
|
55
|
-
specification_version:
|
56
|
-
summary:
|
57
|
-
test_files:
|
58
|
-
|
75
|
+
specification_version: 3
|
76
|
+
summary: Easily write RESTful actions with Sinatra and MongoMapper
|
77
|
+
test_files:
|
78
|
+
- spec/helpers/comments.rb
|
79
|
+
- spec/helpers/posts.rb
|
80
|
+
- spec/helpers/sinatra_stubs.rb
|
81
|
+
- spec/helpers/sources.rb
|
82
|
+
- spec/helpers/spec_helper.rb
|
83
|
+
- spec/spec_helper.rb
|
84
|
+
- spec/unit/posts_and_comments_spec.rb
|
85
|
+
- spec/unit/sources_spec.rb
|
data/rakefile.rb
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
desc "build and install gem"
|
2
|
-
task :gem => ["gem:build", "gem:install"]
|
3
|
-
|
4
|
-
namespace :gem do
|
5
|
-
|
6
|
-
def gem_spec
|
7
|
-
Dir["*.gemspec"].sort.last
|
8
|
-
end
|
9
|
-
|
10
|
-
def gem_file
|
11
|
-
Dir["*.gem"].sort.last
|
12
|
-
end
|
13
|
-
|
14
|
-
desc "build gem"
|
15
|
-
task :build do
|
16
|
-
puts `gem build #{gem_spec}`
|
17
|
-
end
|
18
|
-
|
19
|
-
desc "install gem"
|
20
|
-
task :install do
|
21
|
-
puts `gem install --local --user-install #{gem_file}`
|
22
|
-
end
|
23
|
-
|
24
|
-
end
|