jsonapionify 0.0.1.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.codeclimate.yml +29 -0
- data/.csslintrc +2 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.rubocop.yml +1171 -0
- data/.ruby-version +1 -0
- data/.travis.yml +10 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +4 -0
- data/Guardfile +14 -0
- data/LICENSE.txt +21 -0
- data/README.md +43 -0
- data/Rakefile +34 -0
- data/TODO +13 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/config.ru +15 -0
- data/fixtures/documentation.json +364 -0
- data/jsonapionify.gemspec +50 -0
- data/lib/core_ext/boolean.rb +3 -0
- data/lib/jsonapionify/api/action.rb +211 -0
- data/lib/jsonapionify/api/attribute.rb +67 -0
- data/lib/jsonapionify/api/base/app_builder.rb +33 -0
- data/lib/jsonapionify/api/base/class_methods.rb +73 -0
- data/lib/jsonapionify/api/base/delegation.rb +15 -0
- data/lib/jsonapionify/api/base/doc_helper.rb +47 -0
- data/lib/jsonapionify/api/base/reloader.rb +10 -0
- data/lib/jsonapionify/api/base/resource_definitions.rb +39 -0
- data/lib/jsonapionify/api/base.rb +25 -0
- data/lib/jsonapionify/api/context.rb +14 -0
- data/lib/jsonapionify/api/context_delegate.rb +42 -0
- data/lib/jsonapionify/api/errors.rb +6 -0
- data/lib/jsonapionify/api/errors_object.rb +66 -0
- data/lib/jsonapionify/api/header_options.rb +13 -0
- data/lib/jsonapionify/api/param_options.rb +46 -0
- data/lib/jsonapionify/api/relationship/blocks.rb +41 -0
- data/lib/jsonapionify/api/relationship/many.rb +61 -0
- data/lib/jsonapionify/api/relationship/one.rb +36 -0
- data/lib/jsonapionify/api/relationship.rb +89 -0
- data/lib/jsonapionify/api/resource/builders.rb +81 -0
- data/lib/jsonapionify/api/resource/class_methods.rb +82 -0
- data/lib/jsonapionify/api/resource/defaults/actions.rb +11 -0
- data/lib/jsonapionify/api/resource/defaults/errors.rb +99 -0
- data/lib/jsonapionify/api/resource/defaults/request_contexts.rb +96 -0
- data/lib/jsonapionify/api/resource/defaults/response_contexts.rb +31 -0
- data/lib/jsonapionify/api/resource/defaults.rb +10 -0
- data/lib/jsonapionify/api/resource/definitions/actions.rb +196 -0
- data/lib/jsonapionify/api/resource/definitions/attributes.rb +51 -0
- data/lib/jsonapionify/api/resource/definitions/contexts.rb +16 -0
- data/lib/jsonapionify/api/resource/definitions/helpers.rb +9 -0
- data/lib/jsonapionify/api/resource/definitions/pagination.rb +79 -0
- data/lib/jsonapionify/api/resource/definitions/params.rb +49 -0
- data/lib/jsonapionify/api/resource/definitions/relationships.rb +42 -0
- data/lib/jsonapionify/api/resource/definitions/request_headers.rb +103 -0
- data/lib/jsonapionify/api/resource/definitions/response_headers.rb +22 -0
- data/lib/jsonapionify/api/resource/definitions/scopes.rb +50 -0
- data/lib/jsonapionify/api/resource/definitions/sorting.rb +85 -0
- data/lib/jsonapionify/api/resource/definitions.rb +14 -0
- data/lib/jsonapionify/api/resource/error_handling.rb +108 -0
- data/lib/jsonapionify/api/resource/http.rb +11 -0
- data/lib/jsonapionify/api/resource/includer.rb +4 -0
- data/lib/jsonapionify/api/resource.rb +35 -0
- data/lib/jsonapionify/api/response.rb +47 -0
- data/lib/jsonapionify/api/server/mock_response.rb +37 -0
- data/lib/jsonapionify/api/server/request.rb +78 -0
- data/lib/jsonapionify/api/server.rb +50 -0
- data/lib/jsonapionify/api/test_helper.rb +52 -0
- data/lib/jsonapionify/api.rb +9 -0
- data/lib/jsonapionify/autoload.rb +52 -0
- data/lib/jsonapionify/callbacks.rb +49 -0
- data/lib/jsonapionify/character_range.rb +41 -0
- data/lib/jsonapionify/continuation.rb +26 -0
- data/lib/jsonapionify/documentation/template.erb +487 -0
- data/lib/jsonapionify/documentation.rb +40 -0
- data/lib/jsonapionify/enumerable_observer.rb +91 -0
- data/lib/jsonapionify/indented_string.rb +27 -0
- data/lib/jsonapionify/inherited_attributes.rb +125 -0
- data/lib/jsonapionify/structure/collections/base.rb +104 -0
- data/lib/jsonapionify/structure/collections/errors.rb +7 -0
- data/lib/jsonapionify/structure/collections/included_resources.rb +39 -0
- data/lib/jsonapionify/structure/collections/resource_identifiers.rb +7 -0
- data/lib/jsonapionify/structure/collections/resources.rb +7 -0
- data/lib/jsonapionify/structure/helpers/errors.rb +71 -0
- data/lib/jsonapionify/structure/helpers/inherits_origin.rb +17 -0
- data/lib/jsonapionify/structure/helpers/member_names.rb +37 -0
- data/lib/jsonapionify/structure/helpers/meta_delegate.rb +16 -0
- data/lib/jsonapionify/structure/helpers/object_defaults.rb +123 -0
- data/lib/jsonapionify/structure/helpers/object_setters.rb +21 -0
- data/lib/jsonapionify/structure/helpers/pagination_links.rb +10 -0
- data/lib/jsonapionify/structure/helpers/validations.rb +296 -0
- data/lib/jsonapionify/structure/maps/base.rb +25 -0
- data/lib/jsonapionify/structure/maps/error_links.rb +7 -0
- data/lib/jsonapionify/structure/maps/links.rb +21 -0
- data/lib/jsonapionify/structure/maps/relationship_links.rb +11 -0
- data/lib/jsonapionify/structure/maps/relationships.rb +23 -0
- data/lib/jsonapionify/structure/maps/resource_links.rb +7 -0
- data/lib/jsonapionify/structure/maps/top_level_links.rb +10 -0
- data/lib/jsonapionify/structure/objects/attributes.rb +29 -0
- data/lib/jsonapionify/structure/objects/base.rb +166 -0
- data/lib/jsonapionify/structure/objects/error.rb +16 -0
- data/lib/jsonapionify/structure/objects/included_resource.rb +14 -0
- data/lib/jsonapionify/structure/objects/jsonapi.rb +7 -0
- data/lib/jsonapionify/structure/objects/link.rb +18 -0
- data/lib/jsonapionify/structure/objects/meta.rb +7 -0
- data/lib/jsonapionify/structure/objects/relationship.rb +20 -0
- data/lib/jsonapionify/structure/objects/resource.rb +45 -0
- data/lib/jsonapionify/structure/objects/resource_identifier.rb +40 -0
- data/lib/jsonapionify/structure/objects/source.rb +10 -0
- data/lib/jsonapionify/structure/objects/top_level.rb +105 -0
- data/lib/jsonapionify/structure.rb +27 -0
- data/lib/jsonapionify/types/array_type.rb +32 -0
- data/lib/jsonapionify/types/boolean_type.rb +22 -0
- data/lib/jsonapionify/types/date_string_type.rb +28 -0
- data/lib/jsonapionify/types/float_type.rb +8 -0
- data/lib/jsonapionify/types/integer_type.rb +9 -0
- data/lib/jsonapionify/types/object_type.rb +22 -0
- data/lib/jsonapionify/types/string_type.rb +66 -0
- data/lib/jsonapionify/types/time_string_type.rb +28 -0
- data/lib/jsonapionify/types.rb +49 -0
- data/lib/jsonapionify/unstrict_proc.rb +28 -0
- data/lib/jsonapionify/version.rb +3 -0
- data/lib/jsonapionify.rb +37 -0
- metadata +530 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
module JSONAPIonify
|
2
|
+
class Continuation
|
3
|
+
using UnstrictProc
|
4
|
+
|
5
|
+
def initialize(**options)
|
6
|
+
@options = options
|
7
|
+
end
|
8
|
+
|
9
|
+
def check(*arguments)
|
10
|
+
yield if check_if(*arguments) && check_unless(*arguments)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def check_if(*arguments)
|
16
|
+
return true unless @options[:if]
|
17
|
+
@options[:if].unstrict.call(*arguments)
|
18
|
+
end
|
19
|
+
|
20
|
+
def check_unless(*arguments)
|
21
|
+
return true unless @options[:unless]
|
22
|
+
not @options[:unless].unstrict.call(*arguments)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,487 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
7
|
+
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
|
8
|
+
<title><%= api.title %>></title>
|
9
|
+
|
10
|
+
<link href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAABU1BMVEUAAAAzerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerczerfsspsqAAAAcHRSTlMAAQIDBAYHCAkKCwwNDg8QERIUFRcYGxweICIjJSgqLC0vMDEyNjc6PD5AQUJDREVGR05PVFVXWVthYmZnaGltcHN4fH+AgoiPkZSXmJqdnqKoq62wtbm8vsHDxcfOz9HV19rc4Obo6evt8fX3+fv9oZ9KRwAAAeFJREFUWMPt1NdT1FAYhvE3YRFWLAsWxIYoIkWlCHZQmiCoIIIFFFFAl/78/1deGJ1NOCV4Zrza7y7fOc9vZjczkapTnZxzGXbvhwBjwNcQYBMYCegbAVoCgAFgPwoAloDXuW8XFt/EmQ1ApySp9G3Y23+Cd2mhFaAoSaUyjPp7GE/tJoBVSYp+gEf43XMvtSwDj//+GU4h6Z+klk0AzZKkmvduwdhrENhNXqJbMPf6ALz88+ASLH0tQIf8gqXXDYA6eYXCsrnXFPC5cmEWrL22gYfyCfb+LMA5eQR7rwfAdnaZFQor1l4rwJTcgqs/BtAup+DqdROgVi4hWnb0mgY+Gk8SYVgnANgrGm9FO8CQ2e4CYE3qB+B7venSeYAzxr4NgHJJTuERsOXrXcIXYNLbS30WoR7gmr+3CrcACjl6qdcozAJL1v50amkSoj1g4FB/3dRLdwFYrxQuADTm7E3CU2Azdy/dyQprwJjpC2fuDwnHAa4coZdup4RugJqj9BlhDlgw/P6f9l7qAWBGkuJ9oL/yMD7w9olwVZIuApxKHU76e6kb2iRJz4CNzOELfy+1JB/xdeB59rC9qLxzEuCS/n16gYM4AHgLzAf0MUBPANAA0BAAqHlk9ZWqU53/Nb8AOJAKnq/8xU4AAAAASUVORK5CYII=" rel="icon" type="image/x-icon"/>
|
11
|
+
|
12
|
+
<!-- Bootstrap -->
|
13
|
+
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
|
14
|
+
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.0.0/styles/default.min.css">
|
15
|
+
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.0.0/styles/agate.min.css">
|
16
|
+
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,200,300,500,600,700' rel='stylesheet' type='text/css'>
|
17
|
+
<link href='//fonts.googleapis.com/css?family=Source+Code+Pro:400,200,300,500,600,700' rel='stylesheet' type='text/css'>
|
18
|
+
<style>
|
19
|
+
body {
|
20
|
+
font-family: 'Source Sans Pro', Helvetica, Arial, sans-serif;
|
21
|
+
color: #4c555a;
|
22
|
+
}
|
23
|
+
|
24
|
+
.affix {
|
25
|
+
top: 20px;
|
26
|
+
}
|
27
|
+
|
28
|
+
.navbar-default {
|
29
|
+
border-radius: 0px;
|
30
|
+
background-color: #4c555a;
|
31
|
+
border: 0px;
|
32
|
+
}
|
33
|
+
|
34
|
+
.navbar-default .navbar-collapse, .navbar-default .navbar-form {
|
35
|
+
border-color: transparent;
|
36
|
+
}
|
37
|
+
|
38
|
+
.navbar-default .navbar-brand {
|
39
|
+
color: #e1e8ed;
|
40
|
+
}
|
41
|
+
|
42
|
+
.navbar-default .navbar-brand:hover {
|
43
|
+
color: white;
|
44
|
+
}
|
45
|
+
|
46
|
+
.navbar-default .navbar-nav > li > span {
|
47
|
+
color: #e1e8ed;
|
48
|
+
display: inline-block;
|
49
|
+
padding: 15px;
|
50
|
+
font-size: 14px;
|
51
|
+
font-weight: 300;
|
52
|
+
letter-spacing: 0.3px;
|
53
|
+
}
|
54
|
+
|
55
|
+
/* sidebar */
|
56
|
+
#sidebar {
|
57
|
+
padding-left: 20px;
|
58
|
+
margin-top: 20px;
|
59
|
+
margin-bottom: 20px;
|
60
|
+
}
|
61
|
+
|
62
|
+
#sidebar li.nav-H2 {
|
63
|
+
padding-left: 20px;
|
64
|
+
padding-top: 10px;
|
65
|
+
}
|
66
|
+
|
67
|
+
#sidebar li.nav-H2 > a {
|
68
|
+
color: #939da3;
|
69
|
+
font-weight: 300;
|
70
|
+
text-transform: uppercase;
|
71
|
+
letter-spacing: 1px;
|
72
|
+
font-size: 15px;
|
73
|
+
}
|
74
|
+
|
75
|
+
#sidebar li.nav-H2 > ul {
|
76
|
+
margin-left: 10px;
|
77
|
+
margin-top: 10px;
|
78
|
+
margin-bottom: 10px;
|
79
|
+
}
|
80
|
+
|
81
|
+
#sidebar li.nav-H3 > ul {
|
82
|
+
margin-left: 10px;
|
83
|
+
margin-bottom: 5px;
|
84
|
+
margin-top: 5px;
|
85
|
+
}
|
86
|
+
|
87
|
+
#sidebar li.nav-H4 > a {
|
88
|
+
font-size: 0.9em;
|
89
|
+
}
|
90
|
+
|
91
|
+
/* all links */
|
92
|
+
#sidebar li > a {
|
93
|
+
padding: 0 5px;
|
94
|
+
color: #4c555a;
|
95
|
+
text-decoration: none;
|
96
|
+
border-left: 2px solid transparent;
|
97
|
+
font-size: 15px;
|
98
|
+
font-weight: 400;
|
99
|
+
}
|
100
|
+
|
101
|
+
/* active & hover links */
|
102
|
+
#sidebar .nav-H2.active > a,
|
103
|
+
.bs-docs-sidebar .nav li > a:hover,
|
104
|
+
.bs-docs-sidebar .nav li > a:focus {
|
105
|
+
color: #337ab7;
|
106
|
+
text-decoration: none;
|
107
|
+
background-color: transparent;
|
108
|
+
border-left-color: #337ab7;
|
109
|
+
}
|
110
|
+
|
111
|
+
/* all active links */
|
112
|
+
.bs-docs-sidebar .nav > .active > a,
|
113
|
+
.bs-docs-sidebar .nav > .active:hover > a,
|
114
|
+
.bs-docs-sidebar .nav > .active:focus > a {
|
115
|
+
font-weight: 700;
|
116
|
+
}
|
117
|
+
|
118
|
+
/* nested active links */
|
119
|
+
.bs-docs-sidebar .nav .nav > .active > a,
|
120
|
+
.bs-docs-sidebar .nav .nav > .active:hover > a,
|
121
|
+
.bs-docs-sidebar .nav .nav > .active:focus > a {
|
122
|
+
font-weight: 500;
|
123
|
+
}
|
124
|
+
|
125
|
+
/* hide inactive nested list */
|
126
|
+
#sidebar .nav-H3 ul {
|
127
|
+
display: none;
|
128
|
+
}
|
129
|
+
|
130
|
+
#sidebar .nav-H3:before, .nav-H4:before {
|
131
|
+
content: '>';
|
132
|
+
font-family: "Source Code Pro", Monaco, monospace;
|
133
|
+
position: absolute;
|
134
|
+
left: -5px;
|
135
|
+
color: #e1e8ed;
|
136
|
+
}
|
137
|
+
|
138
|
+
#sidebar .nav-H3.active:before, .nav-H4.active:before {
|
139
|
+
color: #6f7579;
|
140
|
+
content: '>';
|
141
|
+
font-family: "Source Code Pro", Monaco, monospace;
|
142
|
+
position: absolute;
|
143
|
+
left: -5px;
|
144
|
+
}
|
145
|
+
|
146
|
+
/* show active nested list */
|
147
|
+
#sidebar .nav-H3.active > ul {
|
148
|
+
display: block;
|
149
|
+
}
|
150
|
+
|
151
|
+
section {
|
152
|
+
margin-top: 40px;
|
153
|
+
padding-bottom: 40px;
|
154
|
+
border-bottom: 2px solid #e1e8ed;
|
155
|
+
}
|
156
|
+
|
157
|
+
section:first-child {
|
158
|
+
margin-top: 0px;
|
159
|
+
}
|
160
|
+
|
161
|
+
section:last-child {
|
162
|
+
border-bottom: 0px;
|
163
|
+
}
|
164
|
+
|
165
|
+
section.group h3 {
|
166
|
+
margin-bottom: 15px;
|
167
|
+
margin-top: 30px;
|
168
|
+
}
|
169
|
+
|
170
|
+
section.group h4 {
|
171
|
+
margin-top: 30px;
|
172
|
+
font-weight: 300;
|
173
|
+
color: #939da3;
|
174
|
+
text-transform: uppercase;
|
175
|
+
font-size: 13px;
|
176
|
+
letter-spacing: 1px;
|
177
|
+
padding-bottom: 10px;
|
178
|
+
margin-bottom: 0px;
|
179
|
+
border-bottom: 1px solid #e1e8ed;
|
180
|
+
}
|
181
|
+
|
182
|
+
ul.attributes {
|
183
|
+
list-style-type: none;
|
184
|
+
font-size: 14px;
|
185
|
+
padding-left: 0px;
|
186
|
+
}
|
187
|
+
|
188
|
+
ul.attributes .row-attribute {
|
189
|
+
border-bottom: 1px solid #f0f4f7;
|
190
|
+
padding: 15px 0px;
|
191
|
+
}
|
192
|
+
|
193
|
+
ul.relationships {
|
194
|
+
margin-top: 10px;
|
195
|
+
list-style-type: none;
|
196
|
+
padding-left: 0px;
|
197
|
+
}
|
198
|
+
|
199
|
+
ul.attributes > li:last-child > p {
|
200
|
+
margin-bottom: 0px;
|
201
|
+
}
|
202
|
+
|
203
|
+
.attribute-name strong {
|
204
|
+
font-family: 'Source Code Pro', Helvetica, Arial, sans-serif;
|
205
|
+
font-weight: 600;
|
206
|
+
font-size: 13px;
|
207
|
+
}
|
208
|
+
|
209
|
+
.attribute-description {
|
210
|
+
font-size: 14px;
|
211
|
+
}
|
212
|
+
|
213
|
+
ul.attributes .optional, ul.attributes .allowed {,
|
214
|
+
color: #939da3;
|
215
|
+
font-size: 13px;
|
216
|
+
font-weight: 300;
|
217
|
+
margin-bottom: 0px;
|
218
|
+
}
|
219
|
+
|
220
|
+
ul.attributes .allowed {
|
221
|
+
font-style: italic;
|
222
|
+
}
|
223
|
+
|
224
|
+
ul.attributes .optional {
|
225
|
+
margin-top: 5px;
|
226
|
+
}
|
227
|
+
|
228
|
+
footer {
|
229
|
+
margin-top: 60px;
|
230
|
+
padding: 10px 0px;
|
231
|
+
border-top: 1px solid #e7e7e7;
|
232
|
+
background-color: #4c555a;
|
233
|
+
text-align: center;
|
234
|
+
}
|
235
|
+
|
236
|
+
footer a {
|
237
|
+
color: #e1e8ed;
|
238
|
+
}
|
239
|
+
|
240
|
+
footer a:hover {
|
241
|
+
color: white;
|
242
|
+
}
|
243
|
+
|
244
|
+
code.inline {
|
245
|
+
display: inline-block;
|
246
|
+
padding: 0 5px;
|
247
|
+
background: whiteSmoke;
|
248
|
+
border: 1px solid #e7e7e7;
|
249
|
+
-webkit-border-radius: 4px;
|
250
|
+
border-radius: 4px;
|
251
|
+
color: #b93d6a;
|
252
|
+
font-family: 'Source Code Pro', Menlo, monospace;
|
253
|
+
font-size: 12px;
|
254
|
+
line-height: 20px;
|
255
|
+
}
|
256
|
+
|
257
|
+
pre.nostyle {
|
258
|
+
padding: 0px;
|
259
|
+
margin: 0px;
|
260
|
+
border-radius: 0px;
|
261
|
+
position: relative;
|
262
|
+
margin: 10px 0px;
|
263
|
+
padding: 0px;
|
264
|
+
border: 1px solid #e1e8ed;
|
265
|
+
font-size: 12px;
|
266
|
+
line-height: 16px;
|
267
|
+
}
|
268
|
+
|
269
|
+
.attribute-type {
|
270
|
+
color: #939da3
|
271
|
+
}
|
272
|
+
|
273
|
+
pre.nostyle code {
|
274
|
+
padding: 10px 15px;
|
275
|
+
}
|
276
|
+
|
277
|
+
.hljs {
|
278
|
+
background-color: #4c555a;
|
279
|
+
}
|
280
|
+
|
281
|
+
</style>
|
282
|
+
|
283
|
+
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
284
|
+
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
285
|
+
<!--[if lt IE 9]>
|
286
|
+
<script
|
287
|
+
src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
288
|
+
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
289
|
+
<![endif]-->
|
290
|
+
</head>
|
291
|
+
<body>
|
292
|
+
<nav class="navbar navbar-default" role="navigation">
|
293
|
+
<div class="container">
|
294
|
+
<!-- Brand and toggle get grouped for better mobile display -->
|
295
|
+
<div class="navbar-header">
|
296
|
+
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
|
297
|
+
<span class="sr-only">Toggle Description</span>
|
298
|
+
<span class="icon-bar"></span>
|
299
|
+
<span class="icon-bar"></span>
|
300
|
+
<span class="icon-bar"></span>
|
301
|
+
</button>
|
302
|
+
<a class="navbar-brand" href="<%= api.base_url %>">
|
303
|
+
<%= api.title %>
|
304
|
+
</a>
|
305
|
+
</div>
|
306
|
+
</div>
|
307
|
+
</nav>
|
308
|
+
|
309
|
+
<div class="container">
|
310
|
+
<div class="row">
|
311
|
+
|
312
|
+
<!--Main Content -->
|
313
|
+
<div class="col-md-9" id="_main">
|
314
|
+
<section id="api">
|
315
|
+
<h1><%= api.title %></h1>
|
316
|
+
<p><%= api.description %></p>
|
317
|
+
</section>
|
318
|
+
|
319
|
+
<h2>Resources</h2>
|
320
|
+
<% api.resources.each do |resource| %>
|
321
|
+
<section id="<%= resource.name %>" class="group">
|
322
|
+
<h3><%= resource.name.titleize %></h3>
|
323
|
+
|
324
|
+
<p><%= resource.description %></p>
|
325
|
+
|
326
|
+
<div class="details">
|
327
|
+
<h4>Attributes</h4>
|
328
|
+
<ul class="attributes">
|
329
|
+
<% resource.attributes.each do |attribute| %>
|
330
|
+
<li>
|
331
|
+
<div class="row-attribute">
|
332
|
+
<div class="col-xs-4 attribute-name">
|
333
|
+
<strong><%= attribute.name %></strong>
|
334
|
+
<i class="attribute-type"><%= attribute.type %></i>
|
335
|
+
<% if attribute.required %>
|
336
|
+
<p class="optional">required</p>
|
337
|
+
<% else %>
|
338
|
+
<p class="optional">optional</p>
|
339
|
+
<% end %>
|
340
|
+
</div>
|
341
|
+
<div class="col-xs-8 attribute-description">
|
342
|
+
<%= attribute.description.gsub(/`(.*?)`/, "<code class='inline'>\\1</code>") %>
|
343
|
+
<p class="allowed">Allowed: <%= "#{attribute.allow.to_sentence}" %></p>
|
344
|
+
</div>
|
345
|
+
<div style="clear: both;"></div>
|
346
|
+
</div>
|
347
|
+
</li>
|
348
|
+
<% end %>
|
349
|
+
</ul>
|
350
|
+
|
351
|
+
<% resource.actions.each do |action| %>
|
352
|
+
<h4><%= action.name.titleize %> <%= action.name == 'list' ? resource.name.pluralize : resource.name.singularize %></h4>
|
353
|
+
<% action.sample_requests.each do |sample_request| %>
|
354
|
+
<h5>Request</h5>
|
355
|
+
<pre><code class="http"><%= sample_request.request %></code></pre>
|
356
|
+
<h5>Response</h5>
|
357
|
+
<pre><code class="http"><%= sample_request.response %></code></pre>
|
358
|
+
<% end %>
|
359
|
+
<% end %>
|
360
|
+
<h4 id="<%= resource.name %>-relationships">Relationships</h4>
|
361
|
+
<ul class="relationships">
|
362
|
+
<% resource.relationships.each do |relationship| %>
|
363
|
+
<li id="<%= resource.name %>-<%= relationship.name %>" class="subgroup">
|
364
|
+
<strong><a href="#<%= relationship.resource %>"><%= relationship.name %></a></strong>
|
365
|
+
</li>
|
366
|
+
<% end %>
|
367
|
+
</ul>
|
368
|
+
</div>
|
369
|
+
</section>
|
370
|
+
<% end %>
|
371
|
+
|
372
|
+
</div>
|
373
|
+
|
374
|
+
<!--Side Bar -->
|
375
|
+
<nav class="col-md-3 bs-docs-sidebar hidden-sm hidden-xs scrollspy">
|
376
|
+
<ul id="sidebar" class="nav" data-spy="affix"></ul>
|
377
|
+
</nav>
|
378
|
+
|
379
|
+
</div>
|
380
|
+
</div>
|
381
|
+
|
382
|
+
<footer>
|
383
|
+
<div class="container">
|
384
|
+
<div class="row">
|
385
|
+
<div class="col-xs-12">
|
386
|
+
<a href="https://github.com/brandfolder/jsonapionify">
|
387
|
+
Powered by JSONAPIonify
|
388
|
+
</a>
|
389
|
+
</div>
|
390
|
+
</div>
|
391
|
+
</div>
|
392
|
+
</footer>
|
393
|
+
|
394
|
+
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
395
|
+
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
|
396
|
+
<!-- Include all compiled plugins (below), or include individual files as needed -->
|
397
|
+
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha256-KXn5puMvxCw+dAYznun+drMdG1IFl3agK0p/pqT9KAo= sha512-2e8qq0ETcfWRI4HJBzQiA3UoyFk6tbNyG+qSaIBZLyW9Xf3sWZHN/lxe9fTh1U45DpPf07yj94KsUHHWe4Yk1A==" crossorigin="anonymous"></script>
|
398
|
+
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.0.0/highlight.min.js"></script>
|
399
|
+
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.0.0/languages/http.min.js"></script>
|
400
|
+
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>
|
401
|
+
<script>
|
402
|
+
var $sidebar = $('#sidebar');
|
403
|
+
|
404
|
+
var nav = function () {
|
405
|
+
var $e, $prevE;
|
406
|
+
var currentH2 = {}, currentH3 = {}, currentH4 = {};
|
407
|
+
var nav = {};
|
408
|
+
$('#_main h2, #_main h3, #_main h4').each(function (i, e) {
|
409
|
+
var key = 'nav-' + i;
|
410
|
+
$prevE = $e;
|
411
|
+
$e = $(e);
|
412
|
+
switch (e.tagName) {
|
413
|
+
case 'H2':
|
414
|
+
nav[key] = {};
|
415
|
+
nav[key]['_element'] = $e;
|
416
|
+
currentH2 = nav[key];
|
417
|
+
break;
|
418
|
+
case 'H3':
|
419
|
+
currentH2[key] = {};
|
420
|
+
currentH2[key]['_element'] = $e;
|
421
|
+
currentH3 = currentH2[key];
|
422
|
+
break;
|
423
|
+
case 'H4':
|
424
|
+
currentH3[key] = {};
|
425
|
+
currentH3[key]['_element'] = $e;
|
426
|
+
currentH4 = currentH3[key];
|
427
|
+
break;
|
428
|
+
}
|
429
|
+
});
|
430
|
+
return nav
|
431
|
+
}();
|
432
|
+
|
433
|
+
function buildNavigation(map, $list) {
|
434
|
+
$.each(map, function (id, sublist) {
|
435
|
+
if (id == '_element') {
|
436
|
+
return
|
437
|
+
}
|
438
|
+
$e = $(sublist._element);
|
439
|
+
$e.attr('id', id);
|
440
|
+
var $listItem = $('<li class="nav-' + $e[0].tagName + '"></li>');
|
441
|
+
$listItem.append($('<a href="#' + id + '">' + $e.text() + '</a>'));
|
442
|
+
var $subList = $('<ul class="nav"></ul>');
|
443
|
+
buildNavigation(sublist, $subList);
|
444
|
+
if ($subList.find('li').length) {
|
445
|
+
$listItem.append($subList)
|
446
|
+
}
|
447
|
+
$list.append($listItem)
|
448
|
+
})
|
449
|
+
}
|
450
|
+
buildNavigation(nav, $sidebar);
|
451
|
+
$sidebar.find('.nav-H3 ul').addClass('nav-stacked');
|
452
|
+
|
453
|
+
$('body').scrollspy({
|
454
|
+
target: '.bs-docs-sidebar',
|
455
|
+
offset: 40
|
456
|
+
});
|
457
|
+
|
458
|
+
$sidebar.affix({
|
459
|
+
offset: {
|
460
|
+
top: $sidebar.offset().top
|
461
|
+
}
|
462
|
+
});
|
463
|
+
|
464
|
+
hljs.initHighlightingOnLoad();
|
465
|
+
|
466
|
+
$("a[href^='#']").on('click', function (e) {
|
467
|
+
|
468
|
+
// prevent default anchor click behavior
|
469
|
+
e.preventDefault();
|
470
|
+
|
471
|
+
// store hash
|
472
|
+
var hash = this.hash;
|
473
|
+
|
474
|
+
// animate
|
475
|
+
$('html, body').animate({
|
476
|
+
scrollTop: $(hash).offset().top - 20
|
477
|
+
}, 300, function () {
|
478
|
+
|
479
|
+
// when done, add hash to url
|
480
|
+
// (default click behaviour)
|
481
|
+
window.location.hash = hash;
|
482
|
+
});
|
483
|
+
|
484
|
+
});
|
485
|
+
</script>
|
486
|
+
</body>
|
487
|
+
</html>
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'redcarpet'
|
3
|
+
require 'active_support/core_ext/string/inflections'
|
4
|
+
require 'active_support/core_ext/array'
|
5
|
+
|
6
|
+
module JSONAPIonify
|
7
|
+
class Documentation
|
8
|
+
using JSONAPIonify::IndentedString
|
9
|
+
RENDERER = Redcarpet::Markdown.new(
|
10
|
+
Redcarpet::Render::HTML,
|
11
|
+
autolink: true,
|
12
|
+
tables: true,
|
13
|
+
fenced_code_blocks: true,
|
14
|
+
strikethrough: true,
|
15
|
+
disable_indented_code_blocks: true,
|
16
|
+
no_intra_emphasis: true,
|
17
|
+
space_after_headers: true,
|
18
|
+
underline: true,
|
19
|
+
highlight: true,
|
20
|
+
quote: true
|
21
|
+
)
|
22
|
+
|
23
|
+
def self.render_markdown(string)
|
24
|
+
RENDERER.render(string.deindent)
|
25
|
+
end
|
26
|
+
|
27
|
+
attr_reader :api
|
28
|
+
|
29
|
+
def initialize(api, template: nil)
|
30
|
+
template ||= File.join(__dir__, 'documentation/template.erb')
|
31
|
+
@api = api
|
32
|
+
@erb = ERB.new File.read(template)
|
33
|
+
end
|
34
|
+
|
35
|
+
def result
|
36
|
+
@erb.result(binding)
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'jsonapionify/unstrict_proc'
|
2
|
+
|
3
|
+
module JSONAPIonify
|
4
|
+
module EnumerableObserver
|
5
|
+
using UnstrictProc
|
6
|
+
|
7
|
+
def self.observe(obj)
|
8
|
+
Observer.new(obj)
|
9
|
+
end
|
10
|
+
|
11
|
+
def observe(obj = self)
|
12
|
+
Observer.new(obj)
|
13
|
+
end
|
14
|
+
|
15
|
+
class Observer
|
16
|
+
using UnstrictProc
|
17
|
+
|
18
|
+
UNSAFE_METHODS = %i{
|
19
|
+
instance_variable_set
|
20
|
+
remove_instance_variable
|
21
|
+
define_singleton_method
|
22
|
+
instance_eval
|
23
|
+
instance_exec
|
24
|
+
}
|
25
|
+
SAFE_METHODS = (%i{each} + Object.instance_methods) - UNSAFE_METHODS
|
26
|
+
|
27
|
+
private def observer_method_proc(existing = [])
|
28
|
+
array = [self, *existing].freeze
|
29
|
+
lambda do
|
30
|
+
array
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def initialize(obj)
|
35
|
+
@object = obj
|
36
|
+
observers_proc =
|
37
|
+
observer_method_proc(obj.respond_to?(:observers) ? obj.observers : [])
|
38
|
+
obj.define_singleton_method(:observers, &observers_proc)
|
39
|
+
obj.extend mod
|
40
|
+
end
|
41
|
+
|
42
|
+
def mod
|
43
|
+
@mod ||= begin
|
44
|
+
obj = @object
|
45
|
+
blocks = self.blocks
|
46
|
+
Module.new do
|
47
|
+
(obj.methods - SAFE_METHODS).each do |meth|
|
48
|
+
old = obj.method(meth).unbind.bind(obj)
|
49
|
+
define_method(meth) do |*args, &block|
|
50
|
+
before = each.to_a
|
51
|
+
val = old.call(*args, &block)
|
52
|
+
after = each.to_a
|
53
|
+
added = after - before
|
54
|
+
removed = before - after
|
55
|
+
blocks[:add].unstrict.call(added) unless added.empty? || !blocks[:add]
|
56
|
+
blocks[:remove].unstrict.call(removed) unless removed.empty? || !blocks[:remove]
|
57
|
+
val
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def unobserve
|
65
|
+
mod.instance_methods.each do |method_name|
|
66
|
+
mod.module_eval do
|
67
|
+
remove_method method_name
|
68
|
+
end
|
69
|
+
end
|
70
|
+
@unobserved = true
|
71
|
+
end
|
72
|
+
|
73
|
+
def added(&block)
|
74
|
+
blocks[:add] = block
|
75
|
+
self
|
76
|
+
end
|
77
|
+
|
78
|
+
def removed(&block)
|
79
|
+
blocks[:remove] = block
|
80
|
+
self
|
81
|
+
end
|
82
|
+
|
83
|
+
protected
|
84
|
+
|
85
|
+
def blocks
|
86
|
+
@blocks ||= {}
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module JSONAPIonify
|
2
|
+
module IndentedString
|
3
|
+
extend self
|
4
|
+
|
5
|
+
refine String do
|
6
|
+
def deindent
|
7
|
+
shortest_line_length = lines.each_with_object([]) do |line, ary|
|
8
|
+
ary << line.match(/^\s*/)[0].length if line.rstrip.present?
|
9
|
+
end.sort.first
|
10
|
+
|
11
|
+
lines.map do |string|
|
12
|
+
if string.length && !string.match(/^\s*$/)
|
13
|
+
string.rstrip[shortest_line_length..-1]
|
14
|
+
else
|
15
|
+
string
|
16
|
+
end
|
17
|
+
end.join("\n")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
using self
|
22
|
+
|
23
|
+
def deindent_string(string)
|
24
|
+
string.deindent
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|