apipony 0.0.9 → 1.0.0.rc1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7456f0b6bcd79edd941bfba6e1db27e3c0b94f00
4
- data.tar.gz: 08f3bb7e4dfdb5a590a78f8ed2be46b5a475e873
3
+ metadata.gz: c2763c3a557bf3218d2e22427926fa6ccac254a8
4
+ data.tar.gz: 4684d6258f0a056d13b33dc189c48cb9de433da9
5
5
  SHA512:
6
- metadata.gz: d8a9c0b84b6da18245b2dc3187a63ee8ad30de426d45a4fd47f2ee7e384405dd1e4a2665358f0df09b214804157afaa09d0a5c6c2c2410120782c281bfdb79ff
7
- data.tar.gz: 4d7d48df1304b3e316adc35e410ae44f040195127e9dfcd4dca971c6c2dcd806d737ee0ceb31a68c1fd3173b1884333da21b02989c97a252f8390ce8fc45c2c1
6
+ metadata.gz: aa6373f944c15dfcb256dd1a22889426bd6936698733db49285a25d41b5a3eca71125e0f52a683fcbcd16889fae92ca02ed12169027ff01459c6d3fc78cd5f7b
7
+ data.tar.gz: a19bc419ba2fc6bcf86a761bf1710070fc7193ebd65307b68778e877ed2a211b88131a76092633fc405e959c7af7ac25798ea2c199fb0321272dfe0e00da9503
data/README.md CHANGED
@@ -6,246 +6,124 @@
6
6
 
7
7
  Ruby DSL to create Rails API documentation from your application.
8
8
 
9
-
10
- ## Getting started
9
+ ## Getting Started
11
10
  * Add `gem 'apipony'` to Gemfile
12
11
  * `bundle install`
13
12
  * `rails g apipony:install`
14
- * Now you can edit your documentation in `config/initializers/apipony.rb`
13
+ * Edit your documentation in `config/initializers/apipony.rb`
15
14
 
15
+ ![Example](https://raw.githubusercontent.com/droptheplot/apipony/master/preview.png)
16
16
 
17
- ## How it works
18
- DSL example:
17
+ ## Example
19
18
 
20
19
  ```ruby
21
20
  Apipony::Documentation.define do
22
- config do |c|
23
- c.title = 'Apipony Documentation'
24
- c.base_url = '/api/v1'
21
+ configure do
22
+ title 'API Documentation'
23
+ base_url '/api/v1'
25
24
  end
26
25
 
27
26
  section 'Ponies' do
28
- endpoint :get, '/ponies' do |e|
29
- e.description = 'Find ponies'
27
+ endpoint :get, '/ponies' do
28
+ description 'List ponies.'
30
29
 
31
30
  request_with do
32
- param :name, example: 'applejack', required: true
33
- end
31
+ headers do
32
+ {
33
+ 'Accept': 'application/json'
34
+ }
35
+ end
34
36
 
35
- response_with 200 do
36
- attribute :name, type: :string, example: 'applejack'
37
- attribute :kind, type: :string, example: 'earth'
38
- attribute :sex, type: :string, example: 'female'
39
- attribute :occupation, type: :string, example: 'farmer'
37
+ param :name, required: true, description: 'Name of pony.',
38
+ example: :fluttershy
40
39
  end
41
- end
42
- end
43
- end
44
- ```
45
-
46
-
47
- ## Features
48
40
 
49
- ### Response Attribute Documentation
50
- Apipony lets you provide further documentation about the attributes in your
51
- API's responses. Simply create a new `attribute` inside a `response_with` block.
52
- These attributes can even have nested sub-attributes, for documentation of
53
- more complex object graphs.
54
-
55
- ```ruby
56
- Apipony::Documentation.define do
57
- section "Species" do
58
- endpoint 'get', '/species/:id' do |e|
59
- e.description = "Get information about a species"
60
- response_with 200 do
61
- example do
62
- set :body, {
63
- name: "Unicorn",
64
- is_pony: true,
65
- biology: {
66
- has_horn: true,
67
- has_wings: false
41
+ response_with do
42
+ body do
43
+ [
44
+ {
45
+ name: 'Fluttershy',
46
+ kind: 'Pegasus'
68
47
  }
69
- }
70
- end
71
- attribute :name, type: :string
72
- attribute :is_pony, type: :bool,
73
- description: "Is this species a type of pony?"
74
- attribute :biology do
75
- attribute :has_horn, type: :bool
76
- attribute :has_wings, type: :bool
48
+ ]
77
49
  end
78
50
  end
79
51
  end
80
- end
81
- end
82
- ```
83
52
 
84
- ### Enum Attributes
85
- Your API may have some fields that can be picked from a pre-defined set of
86
- values. You can document those values by using an enum attribute.
53
+ endpoint :post, '/ponies' do
54
+ description 'Create new pony.'
87
55
 
88
- ```ruby
89
- Apipony::Documentation.define do
90
- section "Ponies" do
91
- endpoint "get", "/ponies/:id" do |e|
92
- e.description = "Information about a pony"
93
- example do
94
- set :body, {
95
- name: "Applejack",
96
- sex: "female",
97
- kind: :earth,
98
- occupation: :farmer
99
- }
100
- end
101
-
102
- attribute :kind, type: :enum do
103
- choice :earth, description: "A pony with no wings or horn"
104
- choice :unicorn, description: "A pony with a horn"
105
- choice :pegasus, description: "A pony with wings"
106
- choice :alicorn,
107
- description: "A pony with wings and a horn. Indicates royalty."
56
+ request_with do
57
+ param :name, required: true, example: :fluttershy
58
+ param :kind, example: :pegasus
59
+ param :sex, required: true, example: :female
60
+ param :occupation, example: :caretaker,
61
+ description: 'What this pony do for living.'
108
62
  end
109
63
  end
110
- end
111
- end
112
- ```
113
64
 
114
- ### Example Generation
115
- When describing attributes, you can provide an optional `example:` parameter.
116
- If included, this will be used to generate the example response in the
117
- documentation.
65
+ endpoint :put, '/ponies/:id' do
66
+ description 'Update pony by id.'
118
67
 
119
- ```ruby
120
- Apipony::Documentation.define do
121
- section "Ponies" do
122
- endpoint "get", "/ponies/:id" do |e|
123
- response_with 200 do
124
- attribute :name, type: :string, example: "Applejack"
125
- # Enum members automatically select the first choice
126
- attribute :kind, type: :enum do
127
- choice :earth
128
- choice :pegasus
129
- choice :unicorn
130
- choice :alicorn
131
- end
68
+ request_with do
69
+ param :name
70
+ param :kind
71
+ param :sex
72
+ param :occupation
132
73
  end
133
74
  end
134
75
 
135
- endpoint "get", "/ponies/" do |e|
136
- # Automatic serialization of arrays is supported
137
- response_with 200, array: true do
138
- attribute :name, type: :string, example: "Applejack"
139
- attribute :id, type: :integer, example: 10
140
- end
76
+ endpoint :delete, '/ponies/:id' do
77
+ description 'Delete pony by id.'
141
78
  end
142
79
  end
143
- end
144
- ```
145
-
146
- `GET /ponies/:id` will now have the example of:
147
-
148
- ```json
149
- {
150
- "name": "Applejack",
151
- "kind": "Earth"
152
- }
153
- ```
154
-
155
- `GET /ponies/` will have the example of:
156
-
157
- ```json
158
- [
159
- {
160
- "name": "Applejack",
161
- "id": 10
162
- }
163
- ]
164
- ```
165
80
 
166
- ### Predefined Subtypes
167
- Sometimes, when building an API, it can be useful to store data in a common
168
- format. Apipony lets you define this common format once, then use it multiple
169
- times. Check it out:
81
+ section 'Places' do
82
+ endpoint :get, '/places' do
83
+ description 'List places.'
170
84
 
171
- ```ruby
172
- Apipony::Documentation.define do
173
- subtype :pony_stub do
174
- attribute :name, type: :string
175
- attribute :id, type: :integer
176
- end
85
+ response_with do
86
+ status 200
177
87
 
178
- section "Ponies" do
179
- endpoint 'get', '/ponies/:id' do |e|
180
- e.description = "Find a pony with a given name"
181
- request_with do
182
- params :id, example: 10, required: true
183
- end
184
-
185
- response_with 200 do
186
- example do
187
- set :body, {
188
- :name => :applejack,
189
- :type => :earth,
190
- :sex => :female,
191
- :occupation => :farmer,
192
- :friends => [
193
- {name: "Twilight Sparkle", id: 1},
194
- {name: "Pinkie Pie", id: 2},
195
- {name: "Rainbow Dash", id: 3},
196
- {name: "Rarity", id: 4},
197
- {name: "Fluttershy", id: 5}
198
- ]
199
- }
88
+ body do
89
+ [
90
+ {
91
+ name: 'Equestria'
92
+ },
93
+ {
94
+ name: 'Ponyville'
95
+ }
96
+ ]
200
97
  end
201
- attribute :name, type: :string
202
- attribute :kind, type: :enum do
203
- choice :alicorn
204
- choice :earth
205
- choice :unicorn
206
- choice :pegasus
207
98
  end
208
- attribute :friends, type: :pony_stub, array: true
209
- attribute :occupation, type: :string
210
99
  end
211
- end
212
100
 
213
- section "Locations" do
214
- endpoint 'get', '/locations/:id' do |e|
215
- e.description = "Information about a location"
216
- response_with 200 do
217
- example do
218
- set :body, {
219
- :name => "Crystal Empire",
220
- :population => 107770,
221
- :rulers => [
222
- {
223
- name: "Shining Armor",
224
- id: 50
225
- },
226
- {
227
- name: "Princess Cadence",
228
- id: 90001
229
- }
230
- ]
101
+ endpoint :get, '/places/:id' do
102
+ response_with do
103
+ status 200
104
+
105
+ body do
106
+ {
107
+ name: 'Crystal Empire',
108
+ population: 107706
231
109
  }
232
110
  end
233
- attribute :name, type: :string
234
- attribute :population, type: :integer
235
- attribute :rulers, type: :pony_stub, array: true
236
111
  end
237
112
  end
238
113
  end
239
114
  end
240
115
  ```
241
116
 
242
- Now, the `friends` attribute of `GET /ponies/:id` and the `rulers` attribute of
243
- `GET /locations/:id` will reference a common subtype on the generated
244
- documentation.
117
+ By default documentation available here `/apipony`. But you can always change it in `config/routes.rb`.
245
118
 
119
+ ## Contributing
246
120
 
247
- Generated documentation example:
121
+ 1. Fork it (https://github.com/droptheplot/apipony/fork)
122
+ 2. Create your feature branch (git checkout -b my-new-feature)
123
+ 3. Commit your changes (git commit -am 'Add some feature')
124
+ 4. Push to the branch (git push origin my-new-feature)
125
+ 5. Create new Pull Request
248
126
 
249
- ![Example](https://raw.githubusercontent.com/droptheplot/apipony/master/preview.png)
127
+ ## License
250
128
 
251
- By default documentation available here `/apipony`. But you can always change it in `config/routes.rb`.
129
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile CHANGED
@@ -7,17 +7,13 @@ end
7
7
 
8
8
  require 'rdoc/task'
9
9
 
10
- YARD::Rake::YardocTask.new(:doc) do |doc|
11
- end
12
-
13
- APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
14
- load 'rails/tasks/engine.rake'
10
+ YARD::Rake::YardocTask.new(:doc) {}
15
11
 
12
+ APP_RAKEFILE = File.expand_path('../spec/dummy/Rakefile', __FILE__)
16
13
 
14
+ load 'rails/tasks/engine.rake'
17
15
  load 'rails/tasks/statistics.rake'
18
16
 
19
-
20
-
21
17
  Bundler::GemHelper.install_tasks
22
18
 
23
19
  require 'rake/testtask'
@@ -29,5 +25,4 @@ Rake::TestTask.new(:test) do |t|
29
25
  t.verbose = false
30
26
  end
31
27
 
32
-
33
28
  task default: :test
@@ -5,14 +5,14 @@ $light_color: #eee;
5
5
  $brand_color: #5e147d;
6
6
 
7
7
  // Method colors
8
- $get-color: #1abc9c;
9
- $post-color: #3498db;
10
- $put-color: #2980d9;
11
- $delete-color: #c0392b;
8
+ $get_color: #1abc9c;
9
+ $post_color: #3498db;
10
+ $put_color: #2980d9;
11
+ $delete_color: #c0392b;
12
12
 
13
13
  // Misc. values
14
- $transition-time: 200ms;
15
- $mobile-width: 900px;
14
+ $transition_time: 200ms;
15
+ $mobile_width: 900px;
16
16
 
17
17
 
18
18
  *, *::before, *::after {
@@ -57,7 +57,7 @@ h2 {
57
57
  }
58
58
 
59
59
  h3 {
60
- padding-top: 10px;
60
+ margin-bottom: 20px;
61
61
  font-size: 17px;
62
62
  line-height: 16px;
63
63
  }
@@ -96,7 +96,7 @@ ul {
96
96
  display: flex;
97
97
  flex-flow: row nowrap;
98
98
 
99
- @media all and (max-width: $mobile-width) {
99
+ @media all and (max-width: $mobile_width) {
100
100
  flex-flow: row wrap;
101
101
  }
102
102
  }
@@ -105,7 +105,7 @@ ul {
105
105
  flex: 1 80px;
106
106
  margin-right: 40px;
107
107
 
108
- @media all and (max-width: $mobile-width) {
108
+ @media all and (max-width: $mobile_width) {
109
109
  flex: 1 100%;
110
110
  margin-bottom: 30px;
111
111
  }
@@ -120,28 +120,27 @@ ul {
120
120
  .main-col {
121
121
  flex: 8;
122
122
 
123
- @media all and (max-width: $mobile-width) {
123
+ @media all and (max-width: $mobile_width) {
124
124
  flex: 1 100%;
125
125
  }
126
126
  }
127
127
 
128
128
  header {
129
- background: $brand_color;
130
129
  height: 60px;
131
130
  line-height: 60px;
131
+ border-bottom: 1px solid $light_color;
132
132
 
133
133
  .title {
134
134
  font-weight: bold;
135
- font-size: 20px;
136
- color: #fff;
135
+ font-size: 17px;
137
136
  }
138
137
 
139
138
  .back {
140
139
  float: right;
141
- color: #fff;
142
140
  opacity: 0.7;
143
141
  font-size: 12px;
144
- transition: $transition-time opacity;
142
+ transition: $transition_time opacity;
143
+ margin-left: auto;
145
144
 
146
145
  &:hover {
147
146
  opacity: 1;
@@ -163,7 +162,7 @@ footer {
163
162
 
164
163
  a {
165
164
  color: $medium_color;
166
- transition: $transition-time color;
165
+ transition: $transition_time color;
167
166
 
168
167
  &:hover {
169
168
  color: $dark-color;
@@ -185,23 +184,23 @@ footer {
185
184
  margin-bottom: 40px;
186
185
  }
187
186
 
188
- .description {
189
- font-size: 12px;
190
- color: $medium_color;
191
- padding-top: 20px;
192
- font-weight: normal;
193
- }
194
-
195
187
  .response, .request {
196
- padding-top: 20px;
188
+ padding-bottom: 20px;
197
189
 
198
190
  .code {
199
191
  padding: 8px 10px 10px;
200
- font-size: 14px;
192
+ font-size: 12px;
201
193
  border-radius: 0 0 3px 3px;
202
194
  }
203
195
  }
204
196
  }
197
+
198
+ > .description, .endpoint > .description {
199
+ font-size: 12px;
200
+ color: $medium_color;
201
+ padding-bottom: 20px;
202
+ font-weight: normal;
203
+ }
205
204
  }
206
205
 
207
206
  .panel {
@@ -230,23 +229,23 @@ footer {
230
229
  background-color: $medium_color;
231
230
 
232
231
  &.get {
233
- background-color: $get-color;
232
+ background-color: $get_color;
234
233
  }
235
234
 
236
235
  &.post {
237
- background-color: $post-color;
236
+ background-color: $post_color;
238
237
  }
239
238
 
240
239
  &.put {
241
- background-color: $put-color;
240
+ background-color: $put_color;
242
241
  }
243
242
 
244
243
  &.delete {
245
- background-color: $delete-color;
244
+ background-color: $delete_color;
246
245
  }
247
246
  }
248
247
 
249
- .parameters, .attributes {
248
+ .parameter {
250
249
  font-size: 12px;
251
250
 
252
251
  .name {
@@ -266,6 +265,12 @@ footer {
266
265
  color: $medium_color;
267
266
  }
268
267
  }
268
+
269
+ > .description {
270
+ .example {
271
+ color: $medium_color;
272
+ }
273
+ }
269
274
  }
270
275
 
271
276
  .table {
@@ -277,72 +282,3 @@ footer {
277
282
  }
278
283
  }
279
284
  }
280
-
281
- .attribute-container {
282
- display: flex;
283
- flex-flow: column nowrap;
284
-
285
- .attribute {
286
- display: flex;
287
- flex-flow: row nowrap;
288
- align-items: inherit;
289
- justify-content: flex-start;
290
-
291
- > div {
292
- padding: 4px 10px;
293
- }
294
-
295
- .attribute-type {
296
- flex: 1 1 60px;
297
- }
298
-
299
- .attribute-name {
300
- flex: 2 1 0;
301
- min-width: 90px;
302
- }
303
-
304
- .attribute-description {
305
- flex: 8 1 0;
306
- }
307
- }
308
-
309
- ul {
310
- margin: 8px 10px;
311
- border: 1px solid #e1e1e1;
312
- border-radius: 3px;
313
-
314
- li {
315
- list-style: none;
316
- margin: 10px 0;
317
- padding: 0 12px;
318
- }
319
- }
320
- }
321
-
322
- .attribute-enum-member {
323
- display: flex;
324
- flex-flow: row nowrap;
325
-
326
- .title {
327
- border-bottom: 1px solid darken($light_color, 5%);
328
- padding: 10px;
329
- font-size: 11px;
330
- font-weight: bold;
331
- }
332
-
333
- .attribute-enum-member-name {
334
- font-weight: 400;
335
- margin-right: 10px;
336
- min-width: 60px;
337
- flex: 1 1 0;
338
- color: $brand_color;
339
- }
340
-
341
- .attribute-enum-member-description {
342
- flex: 7 1 0;
343
- }
344
- }
345
-
346
- .subtype {
347
- margin-bottom: 25px;
348
- }
@@ -1,8 +1,13 @@
1
1
  <header>
2
2
  <div class="container">
3
- <%= link_to @documentation.title, root_path, class: 'title' %>
4
- <% if main_app.root_path %>
5
- <%= link_to 'Back to site', main_app.root_path, class: 'back' %>
6
- <% end %>
3
+ <div class="row">
4
+ <%= link_to @documentation.data.title, root_path, class: 'title' %>
5
+ <% if main_app.root_path %>
6
+ <%= link_to main_app.root_path, class: 'back' do %>
7
+ <i class='fa fa-home'></i>
8
+ Home
9
+ <% end %>
10
+ <% end %>
11
+ </div>
7
12
  </div>
8
13
  </header>
@@ -1,11 +1,19 @@
1
1
  <div class="request">
2
2
  <h4>Request&#58;</h4>
3
- <% if endpoint.request.params %>
3
+
4
+ <% if endpoint.request.data.headers %>
5
+ <div class="panel">
6
+ <div class="title">Headers</div>
7
+ <pre class="code"><%= JSON.pretty_generate(endpoint.request.data.headers) %></pre>
8
+ </div>
9
+ <% end %>
10
+
11
+ <% if endpoint.request.data.params %>
4
12
  <div class="panel">
5
13
  <div class="title">Parameters</div>
6
14
  <table class="table">
7
- <% endpoint.request.params.each do |param| %>
8
- <tr class="parameters">
15
+ <% endpoint.request.data.params.each do |param| %>
16
+ <tr class="parameter">
9
17
  <td class="name">
10
18
  <%= param.name %>
11
19
  </td>
@@ -19,19 +27,17 @@
19
27
  <i class="fa fa-square-o" title="Optional"></i>
20
28
  <% end %>
21
29
  </td>
22
- <td class="example">
23
- <%= param.example %>
30
+ <td class="description">
31
+ <%= param.description %>
32
+ <% if param.example %>
33
+ <span class="example">
34
+ (example: <strong><%= param.example %></strong>)
35
+ </span>
36
+ <% end %>
24
37
  </td>
25
38
  </tr>
26
39
  <% end %>
27
40
  </table>
28
41
  </div>
29
42
  <% end %>
30
-
31
- <% if endpoint.request.headers %>
32
- <div class="panel">
33
- <div class="title">Headers</div>
34
- <pre class="code"><%= JSON.pretty_generate(endpoint.request.headers) %></pre>
35
- </div>
36
- <% end %>
37
43
  </div>