restivus 0.0.1
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/.DS_Store +0 -0
- data/.document +5 -0
- data/Gemfile +18 -0
- data/Gemfile.lock +42 -0
- data/LICENSE.txt +20 -0
- data/README.md +44 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/examples/banks/Gemfile +3 -0
- data/examples/banks/banklist.csv +451 -0
- data/examples/banks/config.ru +7 -0
- data/examples/banks/main.rb +8 -0
- data/lib/.DS_Store +0 -0
- data/lib/public/.DS_Store +0 -0
- data/lib/public/bootstrap.css +3352 -0
- data/lib/restivus.rb +131 -0
- data/lib/views/.DS_Store +0 -0
- data/lib/views/_sample_request.erb +6 -0
- data/lib/views/docs.erb +53 -0
- data/lib/views/layout.erb +58 -0
- data/test/helper.rb +18 -0
- data/test/test_restivus.rb +7 -0
- metadata +160 -0
data/lib/restivus.rb
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
require 'csv'
|
|
3
|
+
require 'uri'
|
|
4
|
+
require 'sinatra'
|
|
5
|
+
|
|
6
|
+
class Restivus < Sinatra::Base
|
|
7
|
+
|
|
8
|
+
# Doc helpers
|
|
9
|
+
# these methods generate text for the docs pages
|
|
10
|
+
# ------------
|
|
11
|
+
|
|
12
|
+
def curl_req(url)
|
|
13
|
+
`curl #{url}`
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def format_curl_req(url, description="TODO", http="TODO", url_schema="TODO", div="TODO")
|
|
17
|
+
result = {
|
|
18
|
+
:cmd => "$ curl #{url}",
|
|
19
|
+
:raw_response => curl_req(url),
|
|
20
|
+
:pretty_response => JSON.pretty_generate(JSON.parse(curl_req(url))),
|
|
21
|
+
:description => description,
|
|
22
|
+
:http_verb => http,
|
|
23
|
+
:url_schema => url_schema,
|
|
24
|
+
:div_id => div
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
result
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def resource_name
|
|
31
|
+
self.class.name
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def self.fields
|
|
35
|
+
@@fields
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# ----------
|
|
39
|
+
|
|
40
|
+
def self.csv(filename)
|
|
41
|
+
csv_data = CSV.read filename
|
|
42
|
+
headers = csv_data.shift.map {|i| i.to_s }
|
|
43
|
+
headers.map! {|h| h.gsub(" ", "_")}
|
|
44
|
+
@@fields = headers
|
|
45
|
+
string_data = csv_data.map {|row| row.map {|cell| cell.to_s } }
|
|
46
|
+
array_of_hashes = string_data.map {|row| Hash[*headers.zip(row).flatten] }
|
|
47
|
+
@@results = array_of_hashes
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def self.pk(key="id")
|
|
51
|
+
@@pk = key
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def self.find(id)
|
|
55
|
+
where(@@pk => id.to_s).first
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def self.where(conditions={})
|
|
59
|
+
results = @@results.select do |result|
|
|
60
|
+
conditions.all? { |k,v| result[k] == v }
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def self.all
|
|
65
|
+
@@results
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def delete_splat(params)
|
|
69
|
+
%w[splat captures resource].each {|w| params.delete(w)}
|
|
70
|
+
params
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def base_uri
|
|
74
|
+
uri = "http://#{request.host}"
|
|
75
|
+
|
|
76
|
+
if request.port
|
|
77
|
+
uri << ":#{request.port}"
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
uri
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
get "/docs" do
|
|
84
|
+
@fields = self.class.fields
|
|
85
|
+
@base_uri = base_uri
|
|
86
|
+
@resource_name = resource_name
|
|
87
|
+
|
|
88
|
+
@sample_calls = []
|
|
89
|
+
#description="TODO", http="TODO", url_schema="TODO"
|
|
90
|
+
@sample_calls << get_index = format_curl_req("#{@base_uri}/#{@resource_name.downcase}", "Show all #{@resource_name} objects", "GET", "#{@base_uri}/#{@resource_name.downcase}", "index")
|
|
91
|
+
|
|
92
|
+
obj = self.class.all.first
|
|
93
|
+
pk_val = URI.encode(obj[@@pk])
|
|
94
|
+
|
|
95
|
+
@sample_calls << get_show = format_curl_req("#{@base_uri}/#{@resource_name.downcase}/#{pk_val}", "Show individual #{@resource_name} objects by #{@@pk}", "GET", "#{@base_uri}/#{@resource_name.downcase}/<#{@@pk}>", "show")
|
|
96
|
+
|
|
97
|
+
key = obj.keys.last
|
|
98
|
+
val = obj[key]
|
|
99
|
+
|
|
100
|
+
@sample_calls << get_find = format_curl_req("#{@base_uri}/#{@resource_name.downcase}?#{key}=#{val}", "Query #{@resource_name} objects based on parameters", "GET", "#{@base_uri}/#{@resource_name.downcase}?<param>=<value>", "find")
|
|
101
|
+
erb :docs
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
get "/:resource" do
|
|
105
|
+
content_type :json
|
|
106
|
+
case params.keys.length
|
|
107
|
+
when 0 # /:resource
|
|
108
|
+
{"results" => self.class.all}.to_json
|
|
109
|
+
else # /:resource?key=value&...
|
|
110
|
+
constraints = delete_splat(params)
|
|
111
|
+
{"results" => self.class.where(constraints)}.to_json
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
get "/:resource/:id" do
|
|
116
|
+
content_type :json
|
|
117
|
+
self.class.find(params[:id].to_s).to_json
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Usage:
|
|
123
|
+
|
|
124
|
+
#class Person < Restivus
|
|
125
|
+
# csv "example.csv"
|
|
126
|
+
#end
|
|
127
|
+
|
|
128
|
+
#class Bank < Restivus
|
|
129
|
+
# csv "banks.csv"
|
|
130
|
+
# pk "Bank_Name"
|
|
131
|
+
#end
|
data/lib/views/.DS_Store
ADDED
|
Binary file
|
data/lib/views/docs.erb
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
<br /><br /><br />
|
|
2
|
+
<h2>REST API</h2>
|
|
3
|
+
|
|
4
|
+
<p>The REST API lets you interact with <%= @resource_name %> objects using HTTP calls.</p>
|
|
5
|
+
|
|
6
|
+
<h3>Quick Reference</h3>
|
|
7
|
+
|
|
8
|
+
<table class="table">
|
|
9
|
+
<thead>
|
|
10
|
+
<tr>
|
|
11
|
+
<th>URL</th>
|
|
12
|
+
<th>HTTP Verb</th>
|
|
13
|
+
<th>Functionality</th>
|
|
14
|
+
</tr>
|
|
15
|
+
</thead>
|
|
16
|
+
<tbody>
|
|
17
|
+
<% @sample_calls.each do |call| %>
|
|
18
|
+
<tr>
|
|
19
|
+
<td><%= call[:url_schema] %></td>
|
|
20
|
+
<td><%= call[:http_verb] %>
|
|
21
|
+
<td>
|
|
22
|
+
<a href="#<%= call[:div_id] %>">
|
|
23
|
+
<%= call[:description] %>
|
|
24
|
+
</a>
|
|
25
|
+
</td>
|
|
26
|
+
</tr>
|
|
27
|
+
<% end %>
|
|
28
|
+
</tbody>
|
|
29
|
+
</table>
|
|
30
|
+
|
|
31
|
+
<div id="fields" class="span7">
|
|
32
|
+
<h3>Fields</h3>
|
|
33
|
+
|
|
34
|
+
<p>The following are the valid fields of <%= @resource_name %> objects:</p>
|
|
35
|
+
<ul>
|
|
36
|
+
<% @fields.each do |field| %>
|
|
37
|
+
<li><%= field %></li>
|
|
38
|
+
<% end %>
|
|
39
|
+
</ul>
|
|
40
|
+
|
|
41
|
+
</div>
|
|
42
|
+
|
|
43
|
+
<% @sample_calls.each do |call| %>
|
|
44
|
+
<%= erb :_sample_request, :locals => {:sample => call} %>
|
|
45
|
+
<% end %>
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
<div class="span6">
|
|
49
|
+
<footer class="footer">
|
|
50
|
+
<p class="pull-right"><a href="#">Back to top</a></p>
|
|
51
|
+
|
|
52
|
+
</footer>
|
|
53
|
+
</div>
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<html>
|
|
2
|
+
<head>
|
|
3
|
+
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<title><%= @resource_name %> REST API Documentation</title>
|
|
6
|
+
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
7
|
+
|
|
8
|
+
<meta name="viewport"
|
|
9
|
+
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
|
10
|
+
<meta name="description" content="">
|
|
11
|
+
<meta name="author" content="">
|
|
12
|
+
<!--<link rel="stylesheet" href="http://twitter.github.com/bootstrap/1.4.0/bootstrap.min.css">-->
|
|
13
|
+
<link href="/bootstrap.css" rel="stylesheet">
|
|
14
|
+
<link href="/bootstrap-responsive.css" rel="stylesheet">
|
|
15
|
+
|
|
16
|
+
<script type="text/javascript">
|
|
17
|
+
window.addEventListener("load",function() {
|
|
18
|
+
// Set a timeout...
|
|
19
|
+
setTimeout(function(){
|
|
20
|
+
// Hide the address bar!
|
|
21
|
+
window.scrollTo(0, 1);
|
|
22
|
+
}, 0);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
</script
|
|
26
|
+
|
|
27
|
+
</head>
|
|
28
|
+
|
|
29
|
+
<body data-spy="scroll" data-target=".subnav" data-offset="100">
|
|
30
|
+
<div class="navbar navbar-fixed-top">
|
|
31
|
+
<div class="navbar-inner">
|
|
32
|
+
<div class="container">
|
|
33
|
+
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
|
34
|
+
<span class="i-bar"></span>
|
|
35
|
+
<span class="i-bar"></span>
|
|
36
|
+
<span class="i-bar"></span>
|
|
37
|
+
</a>
|
|
38
|
+
<a class="brand" href="/"><%= @resource_name %> Docs</a>
|
|
39
|
+
<div class="nav-collapse">
|
|
40
|
+
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
<div class="container">
|
|
47
|
+
|
|
48
|
+
<!-- Main hero unit for a primary marketing message or call to action -->
|
|
49
|
+
|
|
50
|
+
<%= yield %>
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
</div> <!-- /container -->
|
|
55
|
+
|
|
56
|
+
</body>
|
|
57
|
+
</html>
|
|
58
|
+
|
data/test/helper.rb
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'bundler'
|
|
3
|
+
begin
|
|
4
|
+
Bundler.setup(:default, :development)
|
|
5
|
+
rescue Bundler::BundlerError => e
|
|
6
|
+
$stderr.puts e.message
|
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
|
8
|
+
exit e.status_code
|
|
9
|
+
end
|
|
10
|
+
require 'test/unit'
|
|
11
|
+
require 'shoulda'
|
|
12
|
+
|
|
13
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
|
14
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
|
15
|
+
require 'restivus'
|
|
16
|
+
|
|
17
|
+
class Test::Unit::TestCase
|
|
18
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: restivus
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
prerelease:
|
|
6
|
+
platform: ruby
|
|
7
|
+
authors:
|
|
8
|
+
- Alan deLevie
|
|
9
|
+
autorequire:
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 2012-02-25 00:00:00.000000000Z
|
|
13
|
+
dependencies:
|
|
14
|
+
- !ruby/object:Gem::Dependency
|
|
15
|
+
name: sinatra
|
|
16
|
+
requirement: &70359564562260 !ruby/object:Gem::Requirement
|
|
17
|
+
none: false
|
|
18
|
+
requirements:
|
|
19
|
+
- - ! '>='
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '0'
|
|
22
|
+
type: :runtime
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: *70359564562260
|
|
25
|
+
- !ruby/object:Gem::Dependency
|
|
26
|
+
name: sinatra-respond_to
|
|
27
|
+
requirement: &70359564561380 !ruby/object:Gem::Requirement
|
|
28
|
+
none: false
|
|
29
|
+
requirements:
|
|
30
|
+
- - ! '>='
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: *70359564561380
|
|
36
|
+
- !ruby/object:Gem::Dependency
|
|
37
|
+
name: json
|
|
38
|
+
requirement: &70359564528980 !ruby/object:Gem::Requirement
|
|
39
|
+
none: false
|
|
40
|
+
requirements:
|
|
41
|
+
- - ! '>='
|
|
42
|
+
- !ruby/object:Gem::Version
|
|
43
|
+
version: '0'
|
|
44
|
+
type: :runtime
|
|
45
|
+
prerelease: false
|
|
46
|
+
version_requirements: *70359564528980
|
|
47
|
+
- !ruby/object:Gem::Dependency
|
|
48
|
+
name: active_support
|
|
49
|
+
requirement: &70359564526800 !ruby/object:Gem::Requirement
|
|
50
|
+
none: false
|
|
51
|
+
requirements:
|
|
52
|
+
- - ! '>='
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0'
|
|
55
|
+
type: :runtime
|
|
56
|
+
prerelease: false
|
|
57
|
+
version_requirements: *70359564526800
|
|
58
|
+
- !ruby/object:Gem::Dependency
|
|
59
|
+
name: shoulda
|
|
60
|
+
requirement: &70359564525340 !ruby/object:Gem::Requirement
|
|
61
|
+
none: false
|
|
62
|
+
requirements:
|
|
63
|
+
- - ! '>='
|
|
64
|
+
- !ruby/object:Gem::Version
|
|
65
|
+
version: '0'
|
|
66
|
+
type: :development
|
|
67
|
+
prerelease: false
|
|
68
|
+
version_requirements: *70359564525340
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: bundler
|
|
71
|
+
requirement: &70359564522980 !ruby/object:Gem::Requirement
|
|
72
|
+
none: false
|
|
73
|
+
requirements:
|
|
74
|
+
- - ~>
|
|
75
|
+
- !ruby/object:Gem::Version
|
|
76
|
+
version: 1.0.0
|
|
77
|
+
type: :development
|
|
78
|
+
prerelease: false
|
|
79
|
+
version_requirements: *70359564522980
|
|
80
|
+
- !ruby/object:Gem::Dependency
|
|
81
|
+
name: jeweler
|
|
82
|
+
requirement: &70359564521340 !ruby/object:Gem::Requirement
|
|
83
|
+
none: false
|
|
84
|
+
requirements:
|
|
85
|
+
- - ~>
|
|
86
|
+
- !ruby/object:Gem::Version
|
|
87
|
+
version: 1.6.4
|
|
88
|
+
type: :development
|
|
89
|
+
prerelease: false
|
|
90
|
+
version_requirements: *70359564521340
|
|
91
|
+
- !ruby/object:Gem::Dependency
|
|
92
|
+
name: rcov
|
|
93
|
+
requirement: &70359564519680 !ruby/object:Gem::Requirement
|
|
94
|
+
none: false
|
|
95
|
+
requirements:
|
|
96
|
+
- - ! '>='
|
|
97
|
+
- !ruby/object:Gem::Version
|
|
98
|
+
version: '0'
|
|
99
|
+
type: :development
|
|
100
|
+
prerelease: false
|
|
101
|
+
version_requirements: *70359564519680
|
|
102
|
+
description: Restivus eats CSV files and spits out fully-documented RESTful endpoints.
|
|
103
|
+
email: adelevie@gmail.com
|
|
104
|
+
executables: []
|
|
105
|
+
extensions: []
|
|
106
|
+
extra_rdoc_files:
|
|
107
|
+
- LICENSE.txt
|
|
108
|
+
- README.md
|
|
109
|
+
files:
|
|
110
|
+
- .DS_Store
|
|
111
|
+
- .document
|
|
112
|
+
- Gemfile
|
|
113
|
+
- Gemfile.lock
|
|
114
|
+
- LICENSE.txt
|
|
115
|
+
- README.md
|
|
116
|
+
- Rakefile
|
|
117
|
+
- VERSION
|
|
118
|
+
- examples/banks/Gemfile
|
|
119
|
+
- examples/banks/banklist.csv
|
|
120
|
+
- examples/banks/config.ru
|
|
121
|
+
- examples/banks/main.rb
|
|
122
|
+
- lib/.DS_Store
|
|
123
|
+
- lib/public/.DS_Store
|
|
124
|
+
- lib/public/bootstrap.css
|
|
125
|
+
- lib/restivus.rb
|
|
126
|
+
- lib/views/.DS_Store
|
|
127
|
+
- lib/views/_sample_request.erb
|
|
128
|
+
- lib/views/docs.erb
|
|
129
|
+
- lib/views/layout.erb
|
|
130
|
+
- test/helper.rb
|
|
131
|
+
- test/test_restivus.rb
|
|
132
|
+
homepage: http://github.com/adelevie/restivus
|
|
133
|
+
licenses:
|
|
134
|
+
- MIT
|
|
135
|
+
post_install_message:
|
|
136
|
+
rdoc_options: []
|
|
137
|
+
require_paths:
|
|
138
|
+
- lib
|
|
139
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
140
|
+
none: false
|
|
141
|
+
requirements:
|
|
142
|
+
- - ! '>='
|
|
143
|
+
- !ruby/object:Gem::Version
|
|
144
|
+
version: '0'
|
|
145
|
+
segments:
|
|
146
|
+
- 0
|
|
147
|
+
hash: 1920547086008092273
|
|
148
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
149
|
+
none: false
|
|
150
|
+
requirements:
|
|
151
|
+
- - ! '>='
|
|
152
|
+
- !ruby/object:Gem::Version
|
|
153
|
+
version: '0'
|
|
154
|
+
requirements: []
|
|
155
|
+
rubyforge_project:
|
|
156
|
+
rubygems_version: 1.8.10
|
|
157
|
+
signing_key:
|
|
158
|
+
specification_version: 3
|
|
159
|
+
summary: REST APIs for the rest of us.
|
|
160
|
+
test_files: []
|