rails_api_explorer 0.0.1.pre.1 → 0.0.2.pre.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +96 -0
- data/app/assets/javascripts/api_explorer/application.js +1 -0
- data/app/assets/javascripts/api_explorer/explorer.js +79 -136
- data/app/assets/javascripts/api_explorer/scroll.js +1 -0
- data/app/assets/javascripts/api_explorer/serialize_object.js +54 -0
- data/app/assets/stylesheets/api_explorer/explorer.css +40 -66
- data/app/views/api_explorer/explorer/index.html.erb +18 -16
- data/lib/api_explorer/version.rb +1 -1
- metadata +33 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 92e109fe3ecbff439ba1527c91138e8aea97cae1
|
4
|
+
data.tar.gz: 6ae0e546fab6cb707335daaefe25c6b496658eaa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5941e240df85be5594187045bed33bda332cda60ca1d5115a118eaa09b1ff2724a74be737c22c544fa93b67ab3902abc7c0aee04783c4490cd5e0b2bc31bcde5
|
7
|
+
data.tar.gz: 6a201c1994bd8100f41e6f700e669003c2b2ceae847ccd4c1974f719292f56e8c08179571cb44d26b104900f2a5aea17a831bfc8040297d391c78f1edd11649b
|
data/README.md
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
# rails_api_explorer
|
2
|
+
|
3
|
+
Provides a simple DSL to describe your API, and let's you mount an interactive sandbox to explore and test it.
|
4
|
+
|
5
|
+
[Here's a demo.](http://rails-api-explorer.herokuapp.com)
|
6
|
+
|
7
|
+
This project is in the early stages of development and missing some features. Pull requests are more than welcome!
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem 'rails_api_explorer'
|
15
|
+
```
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
$ bundle
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
Describe your API in `config/initializers/api_explorer.rb`:
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
ApiExplorer.describe do
|
27
|
+
base_url 'http://localhost:3000/api/'
|
28
|
+
|
29
|
+
shared do
|
30
|
+
header 'X-AUTH-TOKEN', source: { request: "POST:users/sign_in", accessor: "['auth_token']"}
|
31
|
+
# The source option makes the value get set automatically when a request to the given url succeeds.
|
32
|
+
# The accessor is evaluated on the JSON object returned by the server.
|
33
|
+
end
|
34
|
+
|
35
|
+
post 'users/sign_in' do
|
36
|
+
desc "Authenticate a user, returns the auth token. Anything except blank values will work for this example."
|
37
|
+
|
38
|
+
exclude_shared_header 'X-AUTH-TOKEN'
|
39
|
+
|
40
|
+
struct 'user_login' do
|
41
|
+
string 'email'
|
42
|
+
string 'password'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
group "Posts" do
|
47
|
+
get 'posts'
|
48
|
+
|
49
|
+
get 'posts/:id' do
|
50
|
+
desc "Returns details for a single post."
|
51
|
+
end
|
52
|
+
|
53
|
+
post 'posts' do
|
54
|
+
desc "Create a post."
|
55
|
+
struct 'post' do
|
56
|
+
string 'title', desc: "Required."
|
57
|
+
string 'body'
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
patch 'posts/:id' do
|
62
|
+
struct 'post' do
|
63
|
+
string 'title', desc: "Required."
|
64
|
+
string 'body'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
```
|
70
|
+
|
71
|
+
Then mount it in your `routes.rb`:
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
mount ApiExplorer::Engine => '/api/explore', as: 'api_explorer'
|
75
|
+
```
|
76
|
+
|
77
|
+
|
78
|
+
If you don't want the public to access the explorer, you can provide a lambda that will be executed in the `before_filter` of the controller:
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
ApiExplorer.auth = lambda do
|
82
|
+
authenticate_user!
|
83
|
+
current_user.admin? or redirect_to main_app.root_path
|
84
|
+
end
|
85
|
+
```
|
86
|
+
|
87
|
+
The explorer is rendered within your application layout and uses bootstrap 3 classes, so it's prettier if you have that included.
|
88
|
+
Bootstrap is optional, but it requires jQuery.
|
89
|
+
|
90
|
+
## Contributing
|
91
|
+
|
92
|
+
1. Fork it
|
93
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
94
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
95
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
96
|
+
5. Create a new Pull Request
|
@@ -1,146 +1,89 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
// Generated by CoffeeScript 1.4.0
|
2
|
+
(function() {
|
3
3
|
|
4
|
+
$(function() {
|
5
|
+
var setValuesFromRequest, updateShareds;
|
6
|
+
$(".hidden").hide().removeClass("hidden");
|
4
7
|
window.responses = {};
|
5
|
-
|
6
8
|
$(".shared-input.header").change(function() {
|
7
|
-
|
8
|
-
});
|
9
|
-
$(".shared-link").click(function() {
|
10
|
-
$($(this).attr("href")).find("input").focus();
|
9
|
+
return updateShareds();
|
11
10
|
});
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
updateShareds = function() {
|
12
|
+
return $(".shared-input.header").each(function() {
|
13
|
+
var name;
|
14
|
+
name = $(this).attr("data-name");
|
15
|
+
return $(".shared.header[data-name=" + name + "]").val($(this).val());
|
16
|
+
});
|
17
|
+
};
|
18
|
+
setValuesFromRequest = function(request) {
|
19
|
+
$("[data-source-request='" + request + "']").each(function(input) {
|
20
|
+
var v;
|
21
|
+
v = eval("responses['" + request + "']" + $(this).attr("data-source-accessor"));
|
22
|
+
return $(this).val(v);
|
23
|
+
});
|
24
|
+
return updateShareds();
|
25
|
+
};
|
26
|
+
$(".param input").prop("disabled", false);
|
27
|
+
$(".send-toggle").click(function(event) {
|
28
|
+
var param, send, setState;
|
29
|
+
event.preventDefault();
|
30
|
+
setState = function(elements, state) {
|
31
|
+
return elements.each(function(i, el) {
|
32
|
+
$(el).attr("data-send", state ? "true" : "false");
|
33
|
+
$(el).find("input").first().prop("disabled", !state);
|
34
|
+
$(el).find(".send-toggle").first().text(state ? "don't send" : "send");
|
35
|
+
return $(el).find(".name").first().toggleClass("strikethrough", !state);
|
17
36
|
});
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
37
|
+
};
|
38
|
+
param = $(this).closest(".param");
|
39
|
+
send = param.attr("data-send") !== "true";
|
40
|
+
setState(param.add(param.find(".param")), send);
|
41
|
+
if (send) {
|
42
|
+
return setState(param.parents(".param"), true);
|
43
|
+
}
|
44
|
+
});
|
45
|
+
return $("form").submit(function(event) {
|
46
|
+
var form, path, req;
|
47
|
+
event.preventDefault();
|
48
|
+
form = $(this);
|
49
|
+
req = form.serializeObject().request;
|
50
|
+
form.closest(".request").find(".status").html("Requesting...");
|
51
|
+
path = req.path;
|
52
|
+
if (req.url_params) {
|
53
|
+
$.each(req.url_params, function(p, v) {
|
54
|
+
return path = path.replace(":" + p, v);
|
24
55
|
});
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
var
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
56
|
+
}
|
57
|
+
return $.ajax({
|
58
|
+
url: path,
|
59
|
+
type: req.method,
|
60
|
+
headers: req.headers,
|
61
|
+
data: req.params,
|
62
|
+
dataType: 'json'
|
63
|
+
}).always(function(data, status, error) {
|
64
|
+
var code, key;
|
65
|
+
if (status === 'success') {
|
66
|
+
code = 200;
|
67
|
+
key = req.method.toUpperCase() + ":" + req.path.replace(api_explorer_base_url, "");
|
68
|
+
window.responses[key] = data;
|
69
|
+
setValuesFromRequest(key);
|
70
|
+
} else {
|
71
|
+
code = data.status;
|
72
|
+
try {
|
73
|
+
data = $.parseJSON(data.responseText);
|
74
|
+
} catch (SyntaxError) {
|
75
|
+
|
76
|
+
}
|
40
77
|
}
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
});
|
48
|
-
|
49
|
-
$("form").submit(function(event) {
|
50
|
-
event.preventDefault();
|
51
|
-
|
52
|
-
var form = $(this);
|
53
|
-
var req = form.serializeObject().request;
|
54
|
-
form.closest(".request").find(".status").html("Requesting...");
|
55
|
-
|
56
|
-
path = req.path;
|
57
|
-
if (req.url_params) {
|
58
|
-
$.each(req.url_params, function(p, v) {
|
59
|
-
path = path.replace(":" + p, v);
|
60
|
-
});
|
78
|
+
if (code === 0) {
|
79
|
+
form.closest(".request").find(".status").text("Can't reach server");
|
80
|
+
return form.closest(".request").find(".response").hide();
|
81
|
+
} else {
|
82
|
+
form.closest(".request").find(".status").text(code);
|
83
|
+
return form.closest(".request").find(".response").text(JSON.stringify(data, null, 4)).show();
|
61
84
|
}
|
62
|
-
|
63
|
-
$.ajax({
|
64
|
-
url: path,
|
65
|
-
type: req.method,
|
66
|
-
headers: req.headers,
|
67
|
-
data: req.params,
|
68
|
-
dataType: 'json'
|
69
|
-
}).always(function(data, status, error) {
|
70
|
-
if(status == 'success') {
|
71
|
-
code = 200;
|
72
|
-
var key = req.method.toUpperCase() + ":" + req.path.replace(api_explorer_base_url, "");
|
73
|
-
window.responses[key] = data;
|
74
|
-
setValuesFromRequest(key);
|
75
|
-
} else {
|
76
|
-
code = data.status;
|
77
|
-
try {
|
78
|
-
data = $.parseJSON(data.responseText);
|
79
|
-
} catch(SyntaxError) {}
|
80
|
-
}
|
81
|
-
if (code == 0) {
|
82
|
-
form.closest(".request").find(".status").text("Can't reach server");
|
83
|
-
form.closest(".request").find(".response").hide();
|
84
|
-
} else {
|
85
|
-
form.closest(".request").find(".status").text(code);
|
86
|
-
form.closest(".request").find(".response").text(JSON.stringify(data, null, 4)).show();
|
87
|
-
}
|
88
|
-
});
|
85
|
+
});
|
89
86
|
});
|
87
|
+
});
|
90
88
|
|
91
|
-
|
92
|
-
$.fn.serializeObject = function() {
|
93
|
-
var self = this,
|
94
|
-
json = {},
|
95
|
-
push_counters = {},
|
96
|
-
patterns = {
|
97
|
-
"validate": /^[a-zA-Z][a-zA-Z0-9_\-]*(?:\[(?:\d*|[a-zA-Z0-9_\-]+)\])*$/,
|
98
|
-
"key": /[a-zA-Z0-9_\-]+|(?=\[\])/g,
|
99
|
-
"push": /^$/,
|
100
|
-
"fixed": /^\d+$/,
|
101
|
-
"named": /^[a-zA-Z0-9_\-]+$/
|
102
|
-
};
|
103
|
-
|
104
|
-
this.build = function(base, key, value){
|
105
|
-
base[key] = value;
|
106
|
-
return base;
|
107
|
-
};
|
108
|
-
this.push_counter = function(key){
|
109
|
-
if(push_counters[key] === undefined){
|
110
|
-
push_counters[key] = 0;
|
111
|
-
}
|
112
|
-
return push_counters[key]++;
|
113
|
-
};
|
114
|
-
$.each($(this).serializeArray(), function(){
|
115
|
-
// skip invalid keys
|
116
|
-
if(!patterns.validate.test(this.name)) {
|
117
|
-
return;
|
118
|
-
}
|
119
|
-
var k,
|
120
|
-
keys = this.name.match(patterns.key),
|
121
|
-
merge = this.value,
|
122
|
-
reverse_key = this.name;
|
123
|
-
|
124
|
-
while((k = keys.pop()) !== undefined){
|
125
|
-
|
126
|
-
// adjust reverse_key
|
127
|
-
reverse_key = reverse_key.replace(new RegExp("\\[" + k + "\\]$"), '');
|
128
|
-
|
129
|
-
// push
|
130
|
-
if(k.match(patterns.push)){
|
131
|
-
merge = self.build([], self.push_counter(reverse_key), merge);
|
132
|
-
}
|
133
|
-
// fixed
|
134
|
-
else if(k.match(patterns.fixed)){
|
135
|
-
merge = self.build([], k, merge);
|
136
|
-
}
|
137
|
-
// named
|
138
|
-
else if(k.match(patterns.named)){
|
139
|
-
merge = self.build({}, k, merge);
|
140
|
-
}
|
141
|
-
}
|
142
|
-
json = $.extend(true, json, merge);
|
143
|
-
});
|
144
|
-
return json;
|
145
|
-
};
|
146
|
-
});
|
89
|
+
}).call(this);
|
@@ -0,0 +1,54 @@
|
|
1
|
+
$.fn.serializeObject = function() {
|
2
|
+
var self = this,
|
3
|
+
json = {},
|
4
|
+
push_counters = {},
|
5
|
+
patterns = {
|
6
|
+
"validate": /^[a-zA-Z][a-zA-Z0-9_\-]*(?:\[(?:\d*|[a-zA-Z0-9_\-]+)\])*$/,
|
7
|
+
"key": /[a-zA-Z0-9_\-]+|(?=\[\])/g,
|
8
|
+
"push": /^$/,
|
9
|
+
"fixed": /^\d+$/,
|
10
|
+
"named": /^[a-zA-Z0-9_\-]+$/
|
11
|
+
};
|
12
|
+
|
13
|
+
this.build = function(base, key, value){
|
14
|
+
base[key] = value;
|
15
|
+
return base;
|
16
|
+
};
|
17
|
+
this.push_counter = function(key){
|
18
|
+
if(push_counters[key] === undefined){
|
19
|
+
push_counters[key] = 0;
|
20
|
+
}
|
21
|
+
return push_counters[key]++;
|
22
|
+
};
|
23
|
+
$.each($(this).serializeArray(), function(){
|
24
|
+
// skip invalid keys
|
25
|
+
if(!patterns.validate.test(this.name)) {
|
26
|
+
return;
|
27
|
+
}
|
28
|
+
var k,
|
29
|
+
keys = this.name.match(patterns.key),
|
30
|
+
merge = this.value,
|
31
|
+
reverse_key = this.name;
|
32
|
+
|
33
|
+
while((k = keys.pop()) !== undefined){
|
34
|
+
|
35
|
+
// adjust reverse_key
|
36
|
+
reverse_key = reverse_key.replace(new RegExp("\\[" + k + "\\]$"), '');
|
37
|
+
|
38
|
+
// push
|
39
|
+
if(k.match(patterns.push)){
|
40
|
+
merge = self.build([], self.push_counter(reverse_key), merge);
|
41
|
+
}
|
42
|
+
// fixed
|
43
|
+
else if(k.match(patterns.fixed)){
|
44
|
+
merge = self.build([], k, merge);
|
45
|
+
}
|
46
|
+
// named
|
47
|
+
else if(k.match(patterns.named)){
|
48
|
+
merge = self.build({}, k, merge);
|
49
|
+
}
|
50
|
+
}
|
51
|
+
json = $.extend(true, json, merge);
|
52
|
+
});
|
53
|
+
return json;
|
54
|
+
};
|
@@ -1,70 +1,44 @@
|
|
1
|
-
.hidden {
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
.
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
}
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
}
|
25
|
-
|
26
|
-
legend {
|
27
|
-
margin-bottom: 5px;
|
28
|
-
}
|
29
|
-
.param-inputs legend {
|
30
|
-
font-size: 100%;
|
31
|
-
border: none;
|
32
|
-
margin-bottom: 0;
|
33
|
-
}
|
34
|
-
label {
|
35
|
-
font-weight: normal;
|
36
|
-
margin-bottom: 0;
|
37
|
-
}
|
38
|
-
|
39
|
-
.response {
|
1
|
+
.api-explorer .hidden {
|
2
|
+
display: none; }
|
3
|
+
.api-explorer .params .params {
|
4
|
+
margin-left: 30px; }
|
5
|
+
.api-explorer .param-inputs .param-inputs {
|
6
|
+
margin-left: 30px; }
|
7
|
+
.api-explorer .param-inputs fieldset {
|
8
|
+
border: none;
|
9
|
+
padding: 0; }
|
10
|
+
.api-explorer .param-inputs input {
|
11
|
+
border: none; }
|
12
|
+
.api-explorer h3 input {
|
13
|
+
border: none;
|
14
|
+
width: 120px;
|
15
|
+
text-align: center; }
|
16
|
+
.api-explorer legend {
|
17
|
+
margin-bottom: 5px; }
|
18
|
+
.api-explorer .param-inputs legend {
|
19
|
+
font-size: 100%;
|
20
|
+
border: none;
|
21
|
+
margin-bottom: 0; }
|
22
|
+
.api-explorer label {
|
23
|
+
font-weight: normal;
|
24
|
+
margin-bottom: 0; }
|
25
|
+
.api-explorer .response {
|
40
26
|
border: solid 1px black;
|
41
27
|
background-color: #CCC;
|
42
28
|
padding: 20px;
|
43
29
|
max-height: 400px;
|
44
|
-
overflow: scroll;
|
45
|
-
|
46
|
-
|
47
|
-
.
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
.send-toggle {
|
60
|
-
font-size: 80%;
|
61
|
-
cursor: pointer;
|
62
|
-
display: none;
|
63
|
-
}
|
64
|
-
:hover > .send-toggle {
|
65
|
-
display: inline;
|
66
|
-
}
|
67
|
-
|
68
|
-
.strikethrough {
|
69
|
-
text-decoration: line-through;
|
70
|
-
}
|
30
|
+
overflow: scroll; }
|
31
|
+
.api-explorer .description {
|
32
|
+
font-size: 80%; }
|
33
|
+
.api-explorer fieldset {
|
34
|
+
margin-bottom: 5px; }
|
35
|
+
.api-explorer legend, .api-explorer label {
|
36
|
+
position: relative; }
|
37
|
+
.api-explorer .send-toggle {
|
38
|
+
font-size: 80%;
|
39
|
+
cursor: pointer;
|
40
|
+
display: none; }
|
41
|
+
.api-explorer :hover > .send-toggle {
|
42
|
+
display: inline; }
|
43
|
+
.api-explorer .strikethrough {
|
44
|
+
text-decoration: line-through; }
|
@@ -1,20 +1,22 @@
|
|
1
|
-
<
|
2
|
-
|
3
|
-
|
1
|
+
<div class="api-explorer">
|
2
|
+
<script type="text/javascript">
|
3
|
+
window.api_explorer_base_url = "<%= @description.base_url %>";
|
4
|
+
</script>
|
4
5
|
|
5
|
-
<%= stylesheet_link_tag "api_explorer/application", media: "all" %>
|
6
|
-
<%= javascript_include_tag "api_explorer/application" %>
|
6
|
+
<%= stylesheet_link_tag "api_explorer/application", media: "all" %>
|
7
|
+
<%= javascript_include_tag "api_explorer/application" %>
|
7
8
|
|
8
|
-
<div class="row">
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
9
|
+
<div class="row">
|
10
|
+
<div class="col-sm-12">
|
11
|
+
<h1>Index</h1>
|
12
|
+
<ul class="contents">
|
13
|
+
<% @description.children.each_with_index do |ch, i| %>
|
14
|
+
<%= render 'content_node', node: ch, id: i %>
|
15
|
+
<% end %>
|
16
|
+
</ul>
|
17
|
+
</div>
|
16
18
|
</div>
|
17
|
-
</div>
|
18
19
|
|
19
|
-
<%= render 'shared' %>
|
20
|
-
<%= render 'node', node: @description, id: "", depth: 0 %>
|
20
|
+
<%= render 'shared' %>
|
21
|
+
<%= render 'node', node: @description, id: "", depth: 0 %>
|
22
|
+
</div>
|
data/lib/api_explorer/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails_api_explorer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2.pre.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Max Hollmann
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-03-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -52,6 +52,34 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: coffee-script
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: sass
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
55
83
|
description: ''
|
56
84
|
email:
|
57
85
|
- maxhollmann@gmail.com
|
@@ -60,10 +88,12 @@ extensions: []
|
|
60
88
|
extra_rdoc_files: []
|
61
89
|
files:
|
62
90
|
- MIT-LICENSE
|
91
|
+
- README.md
|
63
92
|
- Rakefile
|
64
93
|
- app/assets/javascripts/api_explorer/application.js
|
65
94
|
- app/assets/javascripts/api_explorer/explorer.js
|
66
95
|
- app/assets/javascripts/api_explorer/scroll.js
|
96
|
+
- app/assets/javascripts/api_explorer/serialize_object.js
|
67
97
|
- app/assets/stylesheets/api_explorer/application.css
|
68
98
|
- app/assets/stylesheets/api_explorer/explorer.css
|
69
99
|
- app/controllers/api_explorer/application_controller.rb
|
@@ -121,6 +151,6 @@ rubyforge_project:
|
|
121
151
|
rubygems_version: 2.2.2
|
122
152
|
signing_key:
|
123
153
|
specification_version: 4
|
124
|
-
summary: Provides a simple DSL to describe your API, and let's you mount an interactive
|
154
|
+
summary: Provides a simple DSL to describe your JSON API, and let's you mount an interactive
|
125
155
|
sandbox to explore and test it.
|
126
156
|
test_files: []
|