sinatra-backbone 0.1.0.rc1 → 0.1.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY.md +9 -0
- data/examples/restapi/app.rb +40 -0
- data/examples/restapi/config.ru +3 -0
- data/examples/restapi/home.erb +24 -0
- data/examples/restapi/public/app.js +105 -0
- data/lib/sinatra/backbone.rb +1 -2
- data/lib/sinatra/jstpages.rb +1 -1
- data/lib/sinatra/restapi.rb +98 -10
- data/sinatra-backbone.gemspec +1 -0
- data/test/app_test.rb +12 -0
- data/test/arity_test.rb +43 -0
- data/test/emulate_test.rb +30 -0
- data/test/test_helper.rb +1 -0
- metadata +28 -11
data/HISTORY.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
v0.1.0.rc2 - Sep 12, 2011
|
2
|
+
-------------------------
|
3
|
+
|
4
|
+
### Changed:
|
5
|
+
* Check for validity of models on the server, and add an example.
|
6
|
+
* Added examples in the documentation.
|
7
|
+
* Support multiple args in routes.
|
8
|
+
* Added more tests.
|
9
|
+
|
1
10
|
v0.1.0.rc1 - Sept 12, 2011
|
2
11
|
--------------------------
|
3
12
|
|
@@ -0,0 +1,40 @@
|
|
1
|
+
$:.unshift File.expand_path('../../lib', __FILE__)
|
2
|
+
|
3
|
+
require 'sinatra/base'
|
4
|
+
require 'sequel'
|
5
|
+
require 'sinatra/backbone'
|
6
|
+
|
7
|
+
DB = Sequel.connect("sqlite::memory:")
|
8
|
+
DB.create_table :books do
|
9
|
+
primary_key :id
|
10
|
+
String :title
|
11
|
+
String :author
|
12
|
+
end
|
13
|
+
|
14
|
+
class Book < Sequel::Model
|
15
|
+
def to_hash
|
16
|
+
{ :id => id, :title => title, :author => author }
|
17
|
+
end
|
18
|
+
|
19
|
+
def validate
|
20
|
+
errors.add :author, "can't be empty" if author.to_s.size == 0
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class App < Sinatra::Base
|
25
|
+
enable :raise_errors, :logging
|
26
|
+
enable :show_exceptions if development?
|
27
|
+
|
28
|
+
register Sinatra::RestAPI
|
29
|
+
|
30
|
+
rest_create("/book") { Book.new }
|
31
|
+
rest_resource("/book/:id") { |id| Book[id] }
|
32
|
+
|
33
|
+
set :root, File.expand_path('../', __FILE__)
|
34
|
+
set :views, File.expand_path('../', __FILE__)
|
35
|
+
set :public, File.expand_path('../public', __FILE__)
|
36
|
+
|
37
|
+
get '/' do
|
38
|
+
erb :home
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="UTF-8" />
|
5
|
+
<title></title>
|
6
|
+
<script src='http://cdnjs.cloudflare.com/ajax/libs/jquery/1.6.2/jquery.min.js'></script>
|
7
|
+
<script src='http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.1.7/underscore-min.js'></script>
|
8
|
+
<script src='http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.5.3/backbone-min.js'></script>
|
9
|
+
<style>
|
10
|
+
body { font-family: sans-serif; font-size: 13px; line-height: 1.5; background: #d0d0da; }
|
11
|
+
#messages { width: 400px; margin: 20px auto; background: white; padding: 20px; border: solid 10px #c0c0ca; }
|
12
|
+
h3 { border-top: dotted 1px #ccc; padding: 20px 20px 0 20px; margin: 20px -20px 0 -20px; color: #46a; }
|
13
|
+
h3:first-child { border-top: 0; margin-top: 0; padding-top: 0; }
|
14
|
+
dl { overflow: hidden; }
|
15
|
+
dt { float: left; width: 120px; margin-right: 10px; text-align: right; color: #aaa; }
|
16
|
+
h3 { font-family: palatino; font-size: 1.3em; }
|
17
|
+
</style>
|
18
|
+
</head>
|
19
|
+
<body>
|
20
|
+
<div id="messages">
|
21
|
+
</div>
|
22
|
+
<script src='app.js'></script>
|
23
|
+
</body>
|
24
|
+
</html>
|
@@ -0,0 +1,105 @@
|
|
1
|
+
// Here is our Backbone model!
|
2
|
+
Book = Backbone.Model.extend({
|
3
|
+
urlRoot: '/book'
|
4
|
+
});
|
5
|
+
|
6
|
+
$(function() {
|
7
|
+
do_create();
|
8
|
+
});
|
9
|
+
|
10
|
+
function do_create() {
|
11
|
+
echo("<h3>Creating a book:</h3>");
|
12
|
+
|
13
|
+
var book = new Book;
|
14
|
+
book.set({ title: "Darkly Dreaming Dexter", author: "Jeff Lindsay" });
|
15
|
+
book.save({}, {
|
16
|
+
error: onerror,
|
17
|
+
success: function() {
|
18
|
+
print_book(book);
|
19
|
+
echo("<h3>Retrieving the same book:</h3>");
|
20
|
+
do_retrieve(book);
|
21
|
+
}
|
22
|
+
});
|
23
|
+
}
|
24
|
+
|
25
|
+
function do_retrieve(_book) {
|
26
|
+
var book = new Book({ id: _book.id });
|
27
|
+
book.fetch({
|
28
|
+
error: onerror,
|
29
|
+
success: function() {
|
30
|
+
print_book(book);
|
31
|
+
do_edit_error(book);
|
32
|
+
}
|
33
|
+
});
|
34
|
+
}
|
35
|
+
|
36
|
+
function do_edit_error(book) {
|
37
|
+
echo("<h3>Editing book with an error:</h3>");
|
38
|
+
console.log("(You should see an HTTP error right about here:)");
|
39
|
+
book.set({ author: '' });
|
40
|
+
book.save({}, {
|
41
|
+
success: onerror,
|
42
|
+
error: function() {
|
43
|
+
console.log("(...yep.)");
|
44
|
+
echo("...yes, it occured.");
|
45
|
+
do_edit(book);
|
46
|
+
}
|
47
|
+
});
|
48
|
+
}
|
49
|
+
|
50
|
+
function do_edit(book) {
|
51
|
+
echo("<h3>Editing book:</h3>");
|
52
|
+
book.set({ author: 'Anne Rice', title: 'The Claiming of Sleeping Beauty' });
|
53
|
+
book.save({}, {
|
54
|
+
error: onerror,
|
55
|
+
success: function() {
|
56
|
+
print_book(book);
|
57
|
+
do_delete(book);
|
58
|
+
}
|
59
|
+
});
|
60
|
+
}
|
61
|
+
|
62
|
+
function do_delete(book) {
|
63
|
+
echo("<h3>Deleting book:</h3>");
|
64
|
+
book.destroy({
|
65
|
+
error: onerror,
|
66
|
+
success: function() {
|
67
|
+
echo("Success.");
|
68
|
+
do_verify_delete(book.id);
|
69
|
+
}
|
70
|
+
});
|
71
|
+
}
|
72
|
+
|
73
|
+
function do_verify_delete(id) {
|
74
|
+
echo("<h3>Checking if book "+id+" still exists:</h3>");
|
75
|
+
console.log("(You should see an HTTP error right about here:)");
|
76
|
+
var book = new Book({ id: id });
|
77
|
+
book.fetch({
|
78
|
+
success: onerror,
|
79
|
+
error: function() {
|
80
|
+
console.log("(...yep.)");
|
81
|
+
echo("No, it doesn't.");
|
82
|
+
do_success();
|
83
|
+
}
|
84
|
+
});
|
85
|
+
}
|
86
|
+
|
87
|
+
function do_success() {
|
88
|
+
echo("<h3>Success!</h3>");
|
89
|
+
}
|
90
|
+
|
91
|
+
function print_book(book) {
|
92
|
+
echo("<dl><dt>Title:</dt><dd>"+book.get('title')+"</dd></dl>");
|
93
|
+
echo("<dl><dt>Author:</dt><dd>"+book.get('author')+"</dd></dl>");
|
94
|
+
echo("<dl><dt>ID:</dt><dd>"+book.get('id')+"</dd></dl>");
|
95
|
+
}
|
96
|
+
|
97
|
+
// Helper functions
|
98
|
+
function echo(html) {
|
99
|
+
$("#messages").append(html);
|
100
|
+
};
|
101
|
+
|
102
|
+
function onerror() {
|
103
|
+
echo("<p class='error'>Oops... an error occured.</p>");
|
104
|
+
};
|
105
|
+
|
data/lib/sinatra/backbone.rb
CHANGED
data/lib/sinatra/jstpages.rb
CHANGED
data/lib/sinatra/restapi.rb
CHANGED
@@ -12,6 +12,86 @@ require 'json'
|
|
12
12
|
# register Sinatra::RestAPI
|
13
13
|
# end
|
14
14
|
#
|
15
|
+
# ### RestAPI example
|
16
|
+
# Here's a simple example of how to use Backbone models with RestAPI.
|
17
|
+
# Also see the [example application][ex] included in the gem.
|
18
|
+
#
|
19
|
+
# [ex]: https://github.com/rstacruz/sinatra-backbone/tree/master/examples/restapi
|
20
|
+
#
|
21
|
+
# #### Model setup
|
22
|
+
# Let's say you have a `Book` model in your application. Let's use [Sequel][sq]
|
23
|
+
# for this example, but feel free to use any other ORM that is
|
24
|
+
# ActiveModel-compatible.
|
25
|
+
#
|
26
|
+
# You will need to define `to_hash` in your model.
|
27
|
+
#
|
28
|
+
# db = Sequel.connect(...)
|
29
|
+
#
|
30
|
+
# db.create_table :books do
|
31
|
+
# primary_key :id
|
32
|
+
# String :title
|
33
|
+
# String :author
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# class Book < Sequel::Model
|
37
|
+
# # ...
|
38
|
+
# def to_hash
|
39
|
+
# { :title => title, :author => author, :id => id }
|
40
|
+
# end
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# [sq]: http://sequel.rubyforge.org
|
44
|
+
#
|
45
|
+
# #### Sinatra
|
46
|
+
# To provide some routes for Backbone models, use `rest_resource` and
|
47
|
+
# `rest_create`:
|
48
|
+
#
|
49
|
+
# require 'sinatra/restapi'
|
50
|
+
#
|
51
|
+
# class App < Sinatra::Base
|
52
|
+
# register Sinatra::RestAPI
|
53
|
+
#
|
54
|
+
# rest_create '/book' do
|
55
|
+
# Book.new
|
56
|
+
# end
|
57
|
+
#
|
58
|
+
# rest_resource '/book/:id' do |id|
|
59
|
+
# Book.find(:id => id)
|
60
|
+
# end
|
61
|
+
# end
|
62
|
+
#
|
63
|
+
# #### JavaScript
|
64
|
+
# In your JavaScript files, let's make a corresponding model.
|
65
|
+
#
|
66
|
+
# Book = Backbone.Model.extend({
|
67
|
+
# urlRoot: '/book'
|
68
|
+
# });
|
69
|
+
#
|
70
|
+
# Now you may create a new book through your JavaScript:
|
71
|
+
#
|
72
|
+
# book = new Book;
|
73
|
+
# book.set({ title: "Darkly Dreaming Dexter", author: "Jeff Lindsay" });
|
74
|
+
# book.save();
|
75
|
+
#
|
76
|
+
# // In Ruby, equivalent to:
|
77
|
+
# // book = Book.new
|
78
|
+
# // book.title = "Darkly Dreaming Dexter"
|
79
|
+
# // book.author = "Jeff Lindsay"
|
80
|
+
# // book.save
|
81
|
+
#
|
82
|
+
# Or you may retrieve new items. Note that in this example, since we defined
|
83
|
+
# `urlRoot()` but not `url()`, the model URL with default to `/[urlRoot]/[id]`.
|
84
|
+
#
|
85
|
+
# book = new Book({ id: 1 });
|
86
|
+
# book.fetch();
|
87
|
+
#
|
88
|
+
# // In Ruby, equivalent to:
|
89
|
+
# // Book.find(:id => 1)
|
90
|
+
#
|
91
|
+
# Deletes will work just like how you would expect it:
|
92
|
+
#
|
93
|
+
# book.destroy();
|
94
|
+
#
|
15
95
|
module Sinatra::RestAPI
|
16
96
|
def self.registered(app)
|
17
97
|
app.helpers Helpers
|
@@ -32,7 +112,9 @@ module Sinatra::RestAPI
|
|
32
112
|
# your record. For instance, for an attrib like `title`, it wil lbe
|
33
113
|
# calling `object.title = "hello"`.
|
34
114
|
#
|
35
|
-
# * `object.
|
115
|
+
# * if `object.valid?` returns false, it returns an error 400.
|
116
|
+
#
|
117
|
+
# * `object.save` will then be called.
|
36
118
|
#
|
37
119
|
# * `object`'s contents will then be returned to the client as JSON.
|
38
120
|
#
|
@@ -49,6 +131,9 @@ module Sinatra::RestAPI
|
|
49
131
|
post path do
|
50
132
|
@object = yield
|
51
133
|
rest_params.each { |k, v| @object.send :"#{k}=", v }
|
134
|
+
|
135
|
+
return 400, @object.errors.to_json unless @object.valid?
|
136
|
+
|
52
137
|
@object.save
|
53
138
|
rest_respond @object.to_hash
|
54
139
|
end
|
@@ -79,8 +164,8 @@ module Sinatra::RestAPI
|
|
79
164
|
# All the methods above take the same arguments as `rest_resource`.
|
80
165
|
#
|
81
166
|
# class App < Sinatra::Base
|
82
|
-
# rest_resource "/document/:id" do
|
83
|
-
# Document.find(id)
|
167
|
+
# rest_resource "/document/:id" do |id|
|
168
|
+
# Document.find(:id => id)
|
84
169
|
# end
|
85
170
|
# end
|
86
171
|
#
|
@@ -94,8 +179,8 @@ module Sinatra::RestAPI
|
|
94
179
|
# This is the same as `rest_resource`, but only handles *GET* requests.
|
95
180
|
#
|
96
181
|
def rest_get(path, options={}, &blk)
|
97
|
-
get path do |
|
98
|
-
@object = yield(
|
182
|
+
get path do |*args|
|
183
|
+
@object = yield(*args) or pass
|
99
184
|
rest_respond @object
|
100
185
|
end
|
101
186
|
end
|
@@ -105,9 +190,12 @@ module Sinatra::RestAPI
|
|
105
190
|
# requests.
|
106
191
|
#
|
107
192
|
def rest_edit(path, options={}, &blk)
|
108
|
-
callback = Proc.new { |
|
109
|
-
@object = yield(
|
193
|
+
callback = Proc.new { |*args|
|
194
|
+
@object = yield(*args) or pass
|
110
195
|
rest_params.each { |k, v| @object.send :"#{k}=", v unless k == 'id' }
|
196
|
+
|
197
|
+
return 400, @object.errors.to_json unless @object.valid?
|
198
|
+
|
111
199
|
@object.save
|
112
200
|
rest_respond @object
|
113
201
|
}
|
@@ -122,8 +210,8 @@ module Sinatra::RestAPI
|
|
122
210
|
# requests. This uses `Model#destroy` on your model.
|
123
211
|
#
|
124
212
|
def rest_delete(path, options={}, &blk)
|
125
|
-
delete path do |
|
126
|
-
@object = yield(
|
213
|
+
delete path do |*args|
|
214
|
+
@object = yield(*args) or pass
|
127
215
|
@object.destroy
|
128
216
|
rest_respond :result => :success
|
129
217
|
end
|
@@ -167,7 +255,7 @@ module Sinatra::RestAPI
|
|
167
255
|
#
|
168
256
|
# If the client sent a standard URL-encoded POST with a `model` key
|
169
257
|
# (happens when Backbone uses `Backbone.emulateJSON = true`), it tries
|
170
|
-
# to parse
|
258
|
+
# to parse its value as JSON.
|
171
259
|
#
|
172
260
|
# Otherwise, the params will be returned as is.
|
173
261
|
#
|
data/sinatra-backbone.gemspec
CHANGED
@@ -14,5 +14,6 @@ Gem::Specification.new do |s|
|
|
14
14
|
s.add_development_dependency "sequel", ">= 3.25.0"
|
15
15
|
s.add_development_dependency "sqlite3", ">= 1.3.4"
|
16
16
|
s.add_development_dependency "contest"
|
17
|
+
s.add_development_dependency "mocha"
|
17
18
|
s.add_development_dependency "rack-test"
|
18
19
|
end
|
data/test/app_test.rb
CHANGED
@@ -10,6 +10,11 @@ class Book < Sequel::Model
|
|
10
10
|
def to_hash
|
11
11
|
{ :name => name, :author => author }
|
12
12
|
end
|
13
|
+
|
14
|
+
def validate
|
15
|
+
super
|
16
|
+
errors.add(:author, "can't be empty") if author.to_s.size == 0
|
17
|
+
end
|
13
18
|
end
|
14
19
|
|
15
20
|
class AppTest < UnitTest
|
@@ -17,6 +22,7 @@ class AppTest < UnitTest
|
|
17
22
|
register Sinatra::RestAPI
|
18
23
|
disable :show_exceptions
|
19
24
|
enable :raise_errors
|
25
|
+
rest_create("/book") { Book.new }
|
20
26
|
rest_resource("/book/:id") { |id| Book[id] }
|
21
27
|
end
|
22
28
|
def app() App; end
|
@@ -41,6 +47,12 @@ class AppTest < UnitTest
|
|
41
47
|
assert json_response['author'] == @book.author
|
42
48
|
end
|
43
49
|
|
50
|
+
test "validation fail" do
|
51
|
+
hash = { :name => "The Claiming of Sleeping Beauty" }
|
52
|
+
post "/book", :model => hash.to_json
|
53
|
+
p last_response
|
54
|
+
end
|
55
|
+
|
44
56
|
test "should 404" do
|
45
57
|
get "/book/823978"
|
46
58
|
|
data/test/arity_test.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require File.expand_path('../test_helper', __FILE__)
|
2
|
+
|
3
|
+
class ArityTest < UnitTest
|
4
|
+
class FauxModel
|
5
|
+
def initialize(stuff)
|
6
|
+
@stuff = stuff
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_hash
|
10
|
+
{ :contents => @stuff }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class App < Sinatra::Base
|
15
|
+
register Sinatra::RestAPI
|
16
|
+
disable :show_exceptions
|
17
|
+
enable :raise_errors
|
18
|
+
|
19
|
+
rest_resource("/api/:x/:y/:z") { |x, y, z| FauxModel.new ["Hello", x.to_i+1, y.to_i+1, z.to_i+1] }
|
20
|
+
end
|
21
|
+
|
22
|
+
def app() App; end
|
23
|
+
|
24
|
+
describe "Multi args support" do
|
25
|
+
test "get" do
|
26
|
+
header 'Accept', 'application/json, */*'
|
27
|
+
get "/api/20/40/60"
|
28
|
+
|
29
|
+
assert json_response["contents"] = ["Hello", 21, 41, 61]
|
30
|
+
end
|
31
|
+
|
32
|
+
test "put/post" do
|
33
|
+
FauxModel.any_instance.expects(:x=).times(1).returns(true)
|
34
|
+
FauxModel.any_instance.expects(:save).times(1).returns(true)
|
35
|
+
|
36
|
+
header 'Accept', 'application/json, */*'
|
37
|
+
header 'Content-Type', 'application/json'
|
38
|
+
post "/api/20/40/60", JSON.generate('x' => 2)
|
39
|
+
|
40
|
+
assert json_response["contents"] = ["Hello", 21, 41, 61]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require File.expand_path('../test_helper', __FILE__)
|
2
|
+
|
3
|
+
class EmulateTest < UnitTest
|
4
|
+
class App < Sinatra::Base
|
5
|
+
register Sinatra::RestAPI
|
6
|
+
disable :show_exceptions
|
7
|
+
enable :raise_errors
|
8
|
+
|
9
|
+
rest_resource("/api/:id") { |id| FauxModel.new id }
|
10
|
+
end
|
11
|
+
|
12
|
+
def app() App; end
|
13
|
+
|
14
|
+
setup do
|
15
|
+
header 'Accept', 'application/json, */*'
|
16
|
+
end
|
17
|
+
|
18
|
+
test "emulate json and emulate http" do
|
19
|
+
FauxModel.any_instance.expects(:two=).times(1).returns(true)
|
20
|
+
FauxModel.any_instance.expects(:save).times(1).returns(true)
|
21
|
+
FauxModel.any_instance.expects(:to_hash).times(1).returns('a' => 'b')
|
22
|
+
|
23
|
+
post "/api/2", :model => { :two => 2 }.to_json
|
24
|
+
assert json_response == { 'a' => 'b' }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class FauxModel
|
29
|
+
end
|
30
|
+
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sinatra-backbone
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.0.
|
4
|
+
version: 0.1.0.rc2
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -14,7 +14,7 @@ default_executable:
|
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: sinatra
|
17
|
-
requirement: &
|
17
|
+
requirement: &2165346540 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ! '>='
|
@@ -22,10 +22,10 @@ dependencies:
|
|
22
22
|
version: '0'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *2165346540
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: sequel
|
28
|
-
requirement: &
|
28
|
+
requirement: &2165345800 !ruby/object:Gem::Requirement
|
29
29
|
none: false
|
30
30
|
requirements:
|
31
31
|
- - ! '>='
|
@@ -33,10 +33,10 @@ dependencies:
|
|
33
33
|
version: 3.25.0
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
|
-
version_requirements: *
|
36
|
+
version_requirements: *2165345800
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
38
|
name: sqlite3
|
39
|
-
requirement: &
|
39
|
+
requirement: &2165345140 !ruby/object:Gem::Requirement
|
40
40
|
none: false
|
41
41
|
requirements:
|
42
42
|
- - ! '>='
|
@@ -44,10 +44,10 @@ dependencies:
|
|
44
44
|
version: 1.3.4
|
45
45
|
type: :development
|
46
46
|
prerelease: false
|
47
|
-
version_requirements: *
|
47
|
+
version_requirements: *2165345140
|
48
48
|
- !ruby/object:Gem::Dependency
|
49
49
|
name: contest
|
50
|
-
requirement: &
|
50
|
+
requirement: &2165344580 !ruby/object:Gem::Requirement
|
51
51
|
none: false
|
52
52
|
requirements:
|
53
53
|
- - ! '>='
|
@@ -55,10 +55,21 @@ dependencies:
|
|
55
55
|
version: '0'
|
56
56
|
type: :development
|
57
57
|
prerelease: false
|
58
|
-
version_requirements: *
|
58
|
+
version_requirements: *2165344580
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: mocha
|
61
|
+
requirement: &2165343740 !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
type: :development
|
68
|
+
prerelease: false
|
69
|
+
version_requirements: *2165343740
|
59
70
|
- !ruby/object:Gem::Dependency
|
60
71
|
name: rack-test
|
61
|
-
requirement: &
|
72
|
+
requirement: &2165343140 !ruby/object:Gem::Requirement
|
62
73
|
none: false
|
63
74
|
requirements:
|
64
75
|
- - ! '>='
|
@@ -66,7 +77,7 @@ dependencies:
|
|
66
77
|
version: '0'
|
67
78
|
type: :development
|
68
79
|
prerelease: false
|
69
|
-
version_requirements: *
|
80
|
+
version_requirements: *2165343140
|
70
81
|
description: Provides Rest API access to your models and serves JST pages.
|
71
82
|
email:
|
72
83
|
- rico@sinefunc.com
|
@@ -78,6 +89,10 @@ files:
|
|
78
89
|
- HISTORY.md
|
79
90
|
- README.md
|
80
91
|
- Rakefile
|
92
|
+
- examples/restapi/app.rb
|
93
|
+
- examples/restapi/config.ru
|
94
|
+
- examples/restapi/home.erb
|
95
|
+
- examples/restapi/public/app.js
|
81
96
|
- lib/sinatra/backbone.rb
|
82
97
|
- lib/sinatra/jstpages.rb
|
83
98
|
- lib/sinatra/restapi.rb
|
@@ -85,6 +100,8 @@ files:
|
|
85
100
|
- test/app/views/chrome.jst.tpl
|
86
101
|
- test/app/views/editor/edit.jst.jade
|
87
102
|
- test/app_test.rb
|
103
|
+
- test/arity_test.rb
|
104
|
+
- test/emulate_test.rb
|
88
105
|
- test/jst_test.rb
|
89
106
|
- test/test_helper.rb
|
90
107
|
- test/to_json_test.rb
|