respect-rails 0.1.0
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/FAQ.md +98 -0
- data/MIT-LICENSE +20 -0
- data/README.md +291 -0
- data/RELATED_WORK.md +47 -0
- data/RELEASE_NOTES.md +20 -0
- data/Rakefile +32 -0
- data/app/assets/javascripts/respect/rails/schemas.js +32 -0
- data/app/assets/stylesheets/respect/rails/schemas.css +160 -0
- data/app/controllers/respect/rails/schemas_controller.rb +36 -0
- data/app/helpers/respect/rails/schemas_helper.rb +78 -0
- data/app/views/layouts/respect/rails/schemas.html.erb +14 -0
- data/app/views/respect/rails/request_validation_exception.html.erb +38 -0
- data/app/views/respect/rails/schemas/doc.html.erb +158 -0
- data/app/views/respect/rails/schemas/index.html.erb +4 -0
- data/config/routes.rb +4 -0
- data/lib/respect/rails/action_def.rb +37 -0
- data/lib/respect/rails/action_schema.rb +41 -0
- data/lib/respect/rails/application_info.rb +26 -0
- data/lib/respect/rails/controller_helper.rb +107 -0
- data/lib/respect/rails/engine.rb +63 -0
- data/lib/respect/rails/engine_info.rb +27 -0
- data/lib/respect/rails/headers_helper.rb +11 -0
- data/lib/respect/rails/headers_simplifier.rb +31 -0
- data/lib/respect/rails/info.rb +72 -0
- data/lib/respect/rails/request_def.rb +38 -0
- data/lib/respect/rails/request_helper.rb +101 -0
- data/lib/respect/rails/request_schema.rb +102 -0
- data/lib/respect/rails/response_def.rb +43 -0
- data/lib/respect/rails/response_helper.rb +67 -0
- data/lib/respect/rails/response_schema.rb +84 -0
- data/lib/respect/rails/response_schema_set.rb +60 -0
- data/lib/respect/rails/route_info.rb +101 -0
- data/lib/respect/rails/version.rb +5 -0
- data/lib/respect/rails.rb +74 -0
- data/lib/tasks/respect_tasks.rake +4 -0
- data/test/dummy/README.rdoc +261 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/assets/javascripts/application.js +15 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/controllers/automatic_validation_controller.rb +300 -0
- data/test/dummy/app/controllers/caught_exception_controller.rb +58 -0
- data/test/dummy/app/controllers/disabled_controller.rb +37 -0
- data/test/dummy/app/controllers/manual_validation_controller.rb +63 -0
- data/test/dummy/app/controllers/no_schema_controller.rb +17 -0
- data/test/dummy/app/controllers/skipped_automatic_validation_controller.rb +35 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/helpers/respect/application_macros.rb +10 -0
- data/test/dummy/app/helpers/respect/circle_schema.rb +16 -0
- data/test/dummy/app/helpers/respect/point_schema.rb +19 -0
- data/test/dummy/app/helpers/respect/rgba_schema.rb +18 -0
- data/test/dummy/app/views/automatic_validation/request_format.html.erb +1 -0
- data/test/dummy/app/views/automatic_validation/request_format.pdf.erb +1 -0
- data/test/dummy/app/views/caught_exception/response_validator.html.erb +1 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/config/application.rb +58 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +37 -0
- data/test/dummy/config/environments/production.rb +67 -0
- data/test/dummy/config/environments/test.rb +37 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/inflections.rb +15 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/respect.rb +9 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +8 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +38 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/schema.rb +16 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/lib/exts/Rgba.rb +11 -0
- data/test/dummy/lib/exts/circle.rb +11 -0
- data/test/dummy/lib/exts/point.rb +11 -0
- data/test/dummy/log/development.log +6 -0
- data/test/dummy/log/test.log +851 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +25 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/functional/automatic_validation_controller_test.rb +131 -0
- data/test/functional/caught_exception_controller_test.rb +50 -0
- data/test/functional/disabled_controller_test.rb +16 -0
- data/test/functional/manual_validation_controller_test.rb +24 -0
- data/test/functional/no_schema_controller_test.rb +12 -0
- data/test/functional/respect/rails/schemas_controller_test.rb +18 -0
- data/test/functional/skipped_automatic_validation_controller_test.rb +12 -0
- data/test/headers_can_dumped_in_json.sh +33 -0
- data/test/integration/navigation_test.rb +38 -0
- data/test/request_headers_validation_in_dev_mode.sh +33 -0
- data/test/test_helper.rb +17 -0
- data/test/unit/action_schema_test.rb +21 -0
- data/test/unit/application_info_test.rb +11 -0
- data/test/unit/controller_helper_test.rb +4 -0
- data/test/unit/engine_info_test.rb +11 -0
- data/test/unit/engine_test.rb +7 -0
- data/test/unit/info_test.rb +42 -0
- data/test/unit/request_def_test.rb +22 -0
- data/test/unit/request_helper_test.rb +67 -0
- data/test/unit/request_schema_test.rb +164 -0
- data/test/unit/response_def_test.rb +9 -0
- data/test/unit/response_helper_test.rb +73 -0
- data/test/unit/response_schema_set_test.rb +18 -0
- data/test/unit/response_schema_test.rb +147 -0
- metadata +334 -0
data/FAQ.md
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Frequently Asked Question
|
|
2
|
+
|
|
3
|
+
## Why using Respect for Rails since I do most of my parameters checking in my model?
|
|
4
|
+
|
|
5
|
+
This is true that complex parameters ckecking/conversions are often done in the model in
|
|
6
|
+
order to factor code when multiple endpoints use them. For instance, consider the following
|
|
7
|
+
case where the user must provide a circle, via a center point and a radius:
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
class Hotspot < ActiveRecord::Base
|
|
11
|
+
# Returns the list of hot-spots around the given circle.
|
|
12
|
+
#
|
|
13
|
+
# The following statements are equivalent:
|
|
14
|
+
# Hotspot.around(Circle.new(Point.new(42, 51), 16))
|
|
15
|
+
# Hotspot.around(center: { x: 42, y: 51 }, radius: 16)
|
|
16
|
+
def self.around(*args)
|
|
17
|
+
if args.is_a? Hash
|
|
18
|
+
# Build a circle from the hash parameters and call this
|
|
19
|
+
# method recursively.
|
|
20
|
+
self.around(Circle.from_h(args.first))
|
|
21
|
+
else
|
|
22
|
+
circle = args.shift
|
|
23
|
+
# Do the query.
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class HotspotController < ActionController::Base
|
|
29
|
+
def around
|
|
30
|
+
Hotspot.around(params[:area])
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
In this case all the sanitization process is handled by the `Circle::from_h` method. This code
|
|
36
|
+
is ok. However, it has some drawbacks:
|
|
37
|
+
|
|
38
|
+
1. We still have to write the documentation for the REST API and it would be hard to imagine
|
|
39
|
+
a generator that could understand this code or complex `ActiveRecord` validator code.
|
|
40
|
+
1. Although the `Circle::from_h` method may be already provided by a basic third-party library,
|
|
41
|
+
it may not do all the checking necessary when user data come from an HTTP request.
|
|
42
|
+
For instance, it may not handle properly a call like this one:
|
|
43
|
+
`Circle.from_h(center: { x: "foo", y: "bar" }, radius: "invalid")`
|
|
44
|
+
1. In case of invalid schema the user may not get an helpful message. This is perfectly
|
|
45
|
+
acceptable for security reason.
|
|
46
|
+
|
|
47
|
+
We can get _Respect for Rails_ do this work for you by adding a helper method which create a
|
|
48
|
+
`Circle` object for you when validating the JSON document:
|
|
49
|
+
|
|
50
|
+
```ruby
|
|
51
|
+
module Respect
|
|
52
|
+
class PointSchema < CompositeSchema
|
|
53
|
+
def schema_definition
|
|
54
|
+
HashSchema.define do |s|
|
|
55
|
+
s.numeric "x"
|
|
56
|
+
s.numeric "y"
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def sanitize(doc)
|
|
61
|
+
Point.new(doc["x"], doc["y"])
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
class CircleSchema < CompositeSchema
|
|
66
|
+
def schema
|
|
67
|
+
HashSchema.define do |s|
|
|
68
|
+
s.point "center"
|
|
69
|
+
s.numeric "radius", greater_than: 0
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def sanitize(doc)
|
|
74
|
+
Circle.new(doc[:center], doc[:radius])
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
and have your schema written like this
|
|
81
|
+
|
|
82
|
+
```ruby
|
|
83
|
+
class HotspotSchema < Respect::Rails::ActionSchema
|
|
84
|
+
def around
|
|
85
|
+
request do
|
|
86
|
+
schema do |s|
|
|
87
|
+
s.circle "area"
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
_Respect for Rails_ does not aim at replacing `ActiveRecord` validator. In other word, some
|
|
95
|
+
parameters may be validated by _Respect_ and still generate an `ActiveRecord` error. It is here
|
|
96
|
+
to prepare the data for the model, to prevent security issues and to provide a place for
|
|
97
|
+
documenting each parameter. See it as a full featured alternative to
|
|
98
|
+
[Strong Parameters](https://github.com/rails/strong_parameters).
|
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright 2013 YOURNAME
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
# Respect plugin for Rails
|
|
2
|
+
|
|
3
|
+
_Respect for Rails_ let's you write the documentation of your REST API using Ruby code. Your app's
|
|
4
|
+
API is published using a Rails engine so it is always deployed along with your application and stay
|
|
5
|
+
synchronized. A filter is available so you can also easily validate requests and responses. Thanks
|
|
6
|
+
to that your incoming parameters will also be sanitized so if you expect a URI in a parameter value you will get a URI object instead of a string object containing a URI.
|
|
7
|
+
It follows Rails DRY principle and save you a lot of typing since it
|
|
8
|
+
fetches most of the information automatically by inspecting your routes, their constraints and your
|
|
9
|
+
model validators. You can always adjust the default by defining the schema per resource and/or
|
|
10
|
+
controller.
|
|
11
|
+
|
|
12
|
+
# Features
|
|
13
|
+
|
|
14
|
+
* A compact DSL from to the [Respect](https://github.com/nicolasdespres/respect) gem to specify your REST API documentation.
|
|
15
|
+
* Filters to automatically validates and sanitize incoming parameters.
|
|
16
|
+
* A Rails engine to serve your public REST API documentation.
|
|
17
|
+
|
|
18
|
+
See the RELEASE_NOTES file for detailed feature listing.
|
|
19
|
+
|
|
20
|
+
# Take a tour
|
|
21
|
+
|
|
22
|
+
This section guides for a walk around the main features available.
|
|
23
|
+
|
|
24
|
+
## Document an action request
|
|
25
|
+
|
|
26
|
+
_Respect for Rails_ let's you easily describe the structure of incoming requests and outgoing responses
|
|
27
|
+
using a simple and compact Ruby DSL. Assuming you have the scaffold of a `ContactsController`, the structure
|
|
28
|
+
for its `create` action may look like this:
|
|
29
|
+
|
|
30
|
+
```ruby
|
|
31
|
+
# in app/controllers/contacts_controller_schema.rb
|
|
32
|
+
# POST /contacts
|
|
33
|
+
# POST /contacts.json
|
|
34
|
+
def_action_schema :create do |a|
|
|
35
|
+
a.documentation "Create a new contact in the address book."
|
|
36
|
+
a.request do |r|
|
|
37
|
+
r.body_parameters do |s|
|
|
38
|
+
# They look like something like that:
|
|
39
|
+
# { contact: { name: "Albert", age: 62, homepage: "http://example.org" } }
|
|
40
|
+
s.hash "contact" do |s|
|
|
41
|
+
s.string "name", doc: "The name of the contact."
|
|
42
|
+
s.integer "age", doc: "How old is the contact."
|
|
43
|
+
s.uri "homepage", doc: "The URL of the contact's homepage"
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
def create
|
|
49
|
+
# ...
|
|
50
|
+
end
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Note that we distinguish from where the parameters comes from (path, query or body) for the sake of documentation.
|
|
54
|
+
To see the generated doc, you must mount the provided engine like this:
|
|
55
|
+
|
|
56
|
+
```ruby
|
|
57
|
+
# in config/routes.rb
|
|
58
|
+
mount Respect::Rails::Engine => "/rest_spec"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
and point your favorite web browser to `http://localhost:3000/rest_spec`. You should see something like that
|
|
62
|
+
|
|
63
|
+

|
|
64
|
+
|
|
65
|
+
## Document an action response
|
|
66
|
+
|
|
67
|
+
When documenting an API it is also important to write how the response will look like. You can add this code
|
|
68
|
+
to specify the body of the response when the status is "created":
|
|
69
|
+
|
|
70
|
+
```ruby
|
|
71
|
+
# in app/controllers/contacts_controller_schema.rb
|
|
72
|
+
# in def_action_schema :create block
|
|
73
|
+
a.response_for do |status|
|
|
74
|
+
status.created do |r|
|
|
75
|
+
r.body do |s|
|
|
76
|
+
s.integer name, greather_than: 0, doc: "The identifier of this contact."
|
|
77
|
+
s.string "name", doc: "The name of the contact."
|
|
78
|
+
s.integer "age", doc: "How old is the contact."
|
|
79
|
+
s.uri "homepage", doc: "The URL of the contact's homepage"
|
|
80
|
+
s.datetime "created_at", doc: "When this record has been created."
|
|
81
|
+
s.datetime "updated_at", doc: "When this record has been updated lastly."
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
The generated documentation would look like that:
|
|
88
|
+
|
|
89
|
+

|
|
90
|
+
|
|
91
|
+
The specification standard used to document schema is defined at [json-schema.org](http://json-schema.org/)
|
|
92
|
+
(we currenly follow [draft v3](http://tools.ietf.org/id/draft-zyp-json-schema-03.html)).
|
|
93
|
+
|
|
94
|
+
## Factor specification code
|
|
95
|
+
|
|
96
|
+
As you have probably noticed there is some repetition in this code. To avoid it you can create an helper
|
|
97
|
+
like this:
|
|
98
|
+
|
|
99
|
+
```ruby
|
|
100
|
+
# in app/helpers/respect/application_macros.rb
|
|
101
|
+
module Respect
|
|
102
|
+
module ApplicationMacros
|
|
103
|
+
def id(name = "id")
|
|
104
|
+
integer name, greather_than: 0
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def contact_attributes
|
|
108
|
+
string "name", doc: "The name of the contact."
|
|
109
|
+
integer "age", doc: "How old is the contact."
|
|
110
|
+
uri "homepage", doc: "The URL of the contact's homepage"
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def contact
|
|
114
|
+
id
|
|
115
|
+
contact_attributes
|
|
116
|
+
record_timestamps
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def record_timestamps
|
|
120
|
+
doc "When this record has been created."
|
|
121
|
+
datetime "created_at"
|
|
122
|
+
doc "When this record has been updated lastly."
|
|
123
|
+
datetime "updated_at"
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Notice that we have also provided a macro for the usual +id+ attribute. This helper must be install in the
|
|
130
|
+
schema definition DSL like that:
|
|
131
|
+
|
|
132
|
+
```ruby
|
|
133
|
+
# in config/initializers/respect.rb
|
|
134
|
+
Respect::Rails.setup do |config|
|
|
135
|
+
config.helpers Respect::ApplicationMacros
|
|
136
|
+
end
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Now the request schema can be rewritten like this:
|
|
140
|
+
|
|
141
|
+
```ruby
|
|
142
|
+
r.body_parameters do |s|
|
|
143
|
+
s.hash "contact" do |s|
|
|
144
|
+
s.contact_attributes
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
and the response schema like that:
|
|
150
|
+
|
|
151
|
+
```ruby
|
|
152
|
+
r.body do |s|
|
|
153
|
+
s.hash "contact" do |s|
|
|
154
|
+
s.contact
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Validate requests and response
|
|
160
|
+
|
|
161
|
+
All the information you have included in the action specification can also be used to drive a
|
|
162
|
+
validation process. To enable it you just have to install an "around" filter in your
|
|
163
|
+
`ApplicationController` like this:
|
|
164
|
+
|
|
165
|
+
```ruby
|
|
166
|
+
around_filter :validate_schemas!
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Responses formatted in JSON are validated only in development and test mode.
|
|
170
|
+
When validation failed an exception is raised. To help you debug, we provide a more specific
|
|
171
|
+
view than the usual exception reporting view of Rails. You can install this view by adding the
|
|
172
|
+
following line to your `ApplicationController`:
|
|
173
|
+
|
|
174
|
+
```ruby
|
|
175
|
+
rescue_from_request_validation_error if Rails.env.development?
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Sanitize your incoming parameters
|
|
179
|
+
|
|
180
|
+
Incoming requests parameters must often be sanitized since they come from un-trusted users.
|
|
181
|
+
A sanitized version of the request parameters is built along the validation process and stored
|
|
182
|
+
in the `request` object. We can access it using `request.sane_params`. Sanitized object of a
|
|
183
|
+
more specific type than the original parameter value. For instance the `homepage` parameter
|
|
184
|
+
will be a `URI` object instead of a simple string:
|
|
185
|
+
|
|
186
|
+
```ruby
|
|
187
|
+
request.sane_params[:contact][:homepage].class #=> URI::Generic
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
You can also automatically sanitize the request parameters *in-place* by installing this before
|
|
191
|
+
filter:
|
|
192
|
+
|
|
193
|
+
``` ruby
|
|
194
|
+
before_filter :sanitize_params!
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Headers documentation
|
|
198
|
+
|
|
199
|
+
Often REST API expect headers to be set in the request and/or set headers in their responses.
|
|
200
|
+
_Respect for Rails_ let's you document using the `headers` command available for both
|
|
201
|
+
the request and the response.
|
|
202
|
+
|
|
203
|
+
```ruby
|
|
204
|
+
a.request do |r|
|
|
205
|
+
r.headers do |h|
|
|
206
|
+
h.doc "Set this header."
|
|
207
|
+
h['X-AB-Signature'] = "api_public_key"
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Documentation string
|
|
213
|
+
|
|
214
|
+
The DSL let you write documentation string at many places. All this string are structured with a title
|
|
215
|
+
on the first line followed by an empty line and a description for the rest of the string. It is much
|
|
216
|
+
like git commit message except that if there is only one paragraph the title will be omit. You can set
|
|
217
|
+
the documentation like this of most of the item using the `doc` statement or the `:doc` option when
|
|
218
|
+
available. See this example:
|
|
219
|
+
|
|
220
|
+
```ruby
|
|
221
|
+
doc <<-EOS.strip_heredoc
|
|
222
|
+
The name of the contact.
|
|
223
|
+
|
|
224
|
+
First name and last name are separated by white space.
|
|
225
|
+
EOS
|
|
226
|
+
string "name"
|
|
227
|
+
|
|
228
|
+
doc "How old is the contact."
|
|
229
|
+
integer "age"
|
|
230
|
+
|
|
231
|
+
uri "homepage", doc: "The URL of the contact's homepage"
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
# Getting started
|
|
235
|
+
|
|
236
|
+
The easiest way to install _Respect for Rails_ is to add it to your `Gemfile`:
|
|
237
|
+
|
|
238
|
+
```ruby
|
|
239
|
+
gem "respect-rails", require: "respect/rails"
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
Then, after running the `bundle install` command, you can mount the Rails engine provided by this library
|
|
243
|
+
by adding this line at the beginning of your `config/routes.rb` file.
|
|
244
|
+
|
|
245
|
+
```ruby
|
|
246
|
+
mount Respect::Rails::Engine => "/rest_spec"
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
Then, you can start your application web server as usual at point your web browser to
|
|
250
|
+
`http://localhost:3000/rest_spec/doc`.
|
|
251
|
+
|
|
252
|
+
# Getting help
|
|
253
|
+
|
|
254
|
+
The easiest way to get help about how to use this library is to post your question on the
|
|
255
|
+
[Respect for Rails discussion group](https://groups.google.com/forum/#!forum/ruby-respect-gem-talk).
|
|
256
|
+
I will be glade to answer. I may have already answered the
|
|
257
|
+
same question so before, you post your question take a bit of time to search the group.
|
|
258
|
+
|
|
259
|
+
You can also read these documents for further documentation:
|
|
260
|
+
|
|
261
|
+
* [Respect project](https://github.com/nicolasdespres/respect)
|
|
262
|
+
* [Repect API reference documentation](http://nicolasdespres.github.io/respect/)
|
|
263
|
+
* [Repect for Rails API reference documentation](http://nicolasdespres.github.io/respect-rails)
|
|
264
|
+
* The FAQ file.
|
|
265
|
+
|
|
266
|
+
# Compatibility
|
|
267
|
+
|
|
268
|
+
_Respect for Rails_ has been tested with:
|
|
269
|
+
|
|
270
|
+
* Ruby 1.9.3-p392 (should be compatible with all 1.9.x family)
|
|
271
|
+
* Rails 3.2.13
|
|
272
|
+
* Respect 0.1.0
|
|
273
|
+
|
|
274
|
+
Note that it uses `ActiveSupport::JSON` to encode/decode JSON objects.
|
|
275
|
+
|
|
276
|
+
# Feedback
|
|
277
|
+
|
|
278
|
+
I would love to hear what you think about this library. Feel free to post any comments/remarks on the
|
|
279
|
+
[Respect for Rails discussion group](https://groups.google.com/forum/#!forum/ruby-respect-gem-talk).
|
|
280
|
+
|
|
281
|
+
# Contributing patches
|
|
282
|
+
|
|
283
|
+
I spent quite a lot of time writing this gem but there is still a lot of work to do. Whether it
|
|
284
|
+
is a bug-fix, a new feature, some code re-factoring, or documentation clarification, I will be
|
|
285
|
+
glade to merge your pull request on GitHub. You just have to create a branch from `master` and
|
|
286
|
+
send me a pull request.
|
|
287
|
+
|
|
288
|
+
# License
|
|
289
|
+
|
|
290
|
+
_Respect for Rails_ is released under the term of the [MIT License](http://opensource.org/licenses/MIT).
|
|
291
|
+
Copyright (c) 2013 Nicolas Despres.
|
data/RELATED_WORK.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Related works
|
|
2
|
+
|
|
3
|
+
This section describes some projects sharing more or less the same purpose as
|
|
4
|
+
_Respect for Rails_. The goal is to have an overview of the eco-system around this
|
|
5
|
+
topic to borrow ideas and to drive implementation.
|
|
6
|
+
|
|
7
|
+
This section is not meant to be accurate even if we try to stay objective here.
|
|
8
|
+
|
|
9
|
+
## [apipie-rails](https://github.com/Pajk/apipie-rails)
|
|
10
|
+
|
|
11
|
+
* Documentation generation using an engine.
|
|
12
|
+
* Ruby DSL to describe documentation.
|
|
13
|
+
* Support validators.
|
|
14
|
+
* Resource and controllers description API.
|
|
15
|
+
* Good looking generated doc.
|
|
16
|
+
* Allow to statically deployed the documentation apart of the Rails app.
|
|
17
|
+
* Apparently there is no sanitizer.
|
|
18
|
+
* Apparently you can't specify headers.
|
|
19
|
+
* Apparently you can't specify url and query parameters.
|
|
20
|
+
* Apparently there is no support for json-schema.org standard.
|
|
21
|
+
|
|
22
|
+
TODO: Study to be continued...
|
|
23
|
+
|
|
24
|
+
## [Doctorj](https://github.com/coopernurse/doctorj)
|
|
25
|
+
|
|
26
|
+
* No Ruby DSL but uses a Markdown file as input.
|
|
27
|
+
* Syntax to describe schema in Markdown looks compact and close to what we have
|
|
28
|
+
in our Ruby DSL.
|
|
29
|
+
* Generate API documentation in HTML.
|
|
30
|
+
* Not integrated in Rails.
|
|
31
|
+
* Not bind to the routes.
|
|
32
|
+
* No HTTP headers validation possible.
|
|
33
|
+
* No sanitizer.
|
|
34
|
+
|
|
35
|
+
## [Rails::API](https://github.com/rails-api/rails-api)
|
|
36
|
+
|
|
37
|
+
* Lighter Rails for JSON only application.
|
|
38
|
+
|
|
39
|
+
## [Active Model Serializer](https://github.com/rails-api/active_model_serializers)
|
|
40
|
+
|
|
41
|
+
* Object oriented way to organize JSON view code.
|
|
42
|
+
|
|
43
|
+
## [StrongParameters](https://github.com/rails/strong_parameters)
|
|
44
|
+
|
|
45
|
+
* No documentation generation.
|
|
46
|
+
* No sanitizer.
|
|
47
|
+
* No response validation.
|
data/RELEASE_NOTES.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Release notes
|
|
2
|
+
|
|
3
|
+
This document is a list of user visible feature changes made between
|
|
4
|
+
releases except for bug fixes.
|
|
5
|
+
|
|
6
|
+
Note that each entry is kept so brief that no reason behind or
|
|
7
|
+
reference information is supplied with. For a full list of changes
|
|
8
|
+
with all sufficient information, see the git(1) log.
|
|
9
|
+
|
|
10
|
+
A lot more is coming soon check out the issue tagged as `feature`
|
|
11
|
+
in the tracker.
|
|
12
|
+
|
|
13
|
+
## Part of the first release
|
|
14
|
+
|
|
15
|
+
* Feature: An engine to render and deploy the REST API documentation.
|
|
16
|
+
* Feature: Filter to validate requests/responses.
|
|
17
|
+
* Feature: Sanitizer to promote validated parameter value to a more precise type.
|
|
18
|
+
* Feature: Schema are organize like controllers and views.
|
|
19
|
+
* Feature: Follow [JSON schema draft v3 standard](http://tools.ietf.org/id/draft-zyp-json-schema-03.html) to represents schema.
|
|
20
|
+
* Feature: A RequestValidationError exception handler.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/usr/bin/env rake
|
|
2
|
+
begin
|
|
3
|
+
require 'bundler/setup'
|
|
4
|
+
rescue LoadError
|
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
require 'yard'
|
|
9
|
+
YARD::Rake::YardocTask.new do |t|
|
|
10
|
+
t.files = [
|
|
11
|
+
'lib/**/*.rb',
|
|
12
|
+
'-',
|
|
13
|
+
'README.md',
|
|
14
|
+
'FAQ.md',
|
|
15
|
+
'RELEASE_NOTES.md',
|
|
16
|
+
'RELATED_WORK.md',
|
|
17
|
+
]
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
Bundler::GemHelper.install_tasks
|
|
21
|
+
|
|
22
|
+
require 'rake/testtask'
|
|
23
|
+
|
|
24
|
+
Rake::TestTask.new(:test) do |t|
|
|
25
|
+
t.libs << 'lib'
|
|
26
|
+
t.libs << 'test'
|
|
27
|
+
t.pattern = 'test/**/*_test.rb'
|
|
28
|
+
t.verbose = false
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
task :default => :test
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
|
2
|
+
// listed below.
|
|
3
|
+
//
|
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
|
5
|
+
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
|
|
6
|
+
//
|
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
|
8
|
+
// the compiled file.
|
|
9
|
+
//
|
|
10
|
+
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
|
|
11
|
+
// GO AFTER THE REQUIRES BELOW.
|
|
12
|
+
//
|
|
13
|
+
//= require jquery
|
|
14
|
+
//= require jquery_ujs
|
|
15
|
+
//= require_tree .
|
|
16
|
+
|
|
17
|
+
var toggle = function(id) {
|
|
18
|
+
var s = document.getElementById("toggle_" + id).style;
|
|
19
|
+
var t = document.getElementById("toggle_" + id + "_toggle");
|
|
20
|
+
if (s.display == 'none') {
|
|
21
|
+
s.display = 'block';
|
|
22
|
+
t.innerHTML = t.innerHTML.replace(/^Show/, 'Hide');
|
|
23
|
+
} else {
|
|
24
|
+
s.display = 'none';
|
|
25
|
+
t.innerHTML = t.innerHTML.replace(/^Hide/, 'Show');
|
|
26
|
+
}
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
var toggleHeadersDump = function() {
|
|
31
|
+
return toggle('headers_dump');
|
|
32
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
|
3
|
+
* listed below.
|
|
4
|
+
*
|
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
|
6
|
+
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
|
|
7
|
+
*
|
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the top of the
|
|
9
|
+
* compiled file, but it's generally better to create a new file per style scope.
|
|
10
|
+
*
|
|
11
|
+
*= require_self
|
|
12
|
+
*= require_tree .
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
body { background-color: #fff; color: #333; }
|
|
16
|
+
|
|
17
|
+
body, p, ol, ul, td {
|
|
18
|
+
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
|
19
|
+
font-size: 14px;
|
|
20
|
+
line-height: 1.4;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
body {
|
|
24
|
+
padding-top: 20px;
|
|
25
|
+
padding-bottom: 40px;
|
|
26
|
+
width: 1024px;
|
|
27
|
+
margin-left: auto;
|
|
28
|
+
margin-right: auto;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
pre {
|
|
32
|
+
background-color: #f8f8f8;
|
|
33
|
+
padding: 10px;
|
|
34
|
+
font-family: monospace;
|
|
35
|
+
font-size: 13px;
|
|
36
|
+
white-space: pre;
|
|
37
|
+
border-style: solid;
|
|
38
|
+
border-width: 1px;
|
|
39
|
+
border-color: #ccc;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
a {
|
|
43
|
+
color: rgb(205, 91, 69);
|
|
44
|
+
text-decoration: none;
|
|
45
|
+
}
|
|
46
|
+
a:hover {
|
|
47
|
+
color: rgb(205, 91, 69);
|
|
48
|
+
text-decoration: underline;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
h1 {
|
|
52
|
+
font-size: 30px;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
h2 {
|
|
56
|
+
font-size: 27px;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
h3 {
|
|
60
|
+
font-size: 22px;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
hr {
|
|
64
|
+
border-color: rgb(205, 91, 69);
|
|
65
|
+
border-width: 4px;
|
|
66
|
+
border-style: solid;
|
|
67
|
+
margin-top: 50px;
|
|
68
|
+
margin-bottom: 50px;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
table {
|
|
72
|
+
width: 100%;
|
|
73
|
+
border-spacing: 0px;
|
|
74
|
+
border-collapse: collapse;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
tr:hover {
|
|
78
|
+
background-color: rgb(255, 240, 237);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
td {
|
|
82
|
+
padding-top: 6px;
|
|
83
|
+
padding-bottom: 6px;
|
|
84
|
+
padding-left: 8px;
|
|
85
|
+
border-top-style: solid;
|
|
86
|
+
border-top-width: 1px;
|
|
87
|
+
border-top-color: #ccc;
|
|
88
|
+
border-bottom-style: solid;
|
|
89
|
+
border-bottom-width: 1px;
|
|
90
|
+
border-bottom-color: #ccc;
|
|
91
|
+
text-align: left;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.summary {
|
|
95
|
+
padding-top: 15px;
|
|
96
|
+
padding-left: 15px;
|
|
97
|
+
display: block;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
/* Table of contents */
|
|
102
|
+
|
|
103
|
+
.toc .title {
|
|
104
|
+
border-bottom-width: 1px;
|
|
105
|
+
border-bottom-style: solid;
|
|
106
|
+
border-bottom-color: rgb(205, 91, 69);
|
|
107
|
+
line-height: 30px;
|
|
108
|
+
margin-bottom: 40px;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.toc h3 {
|
|
112
|
+
color: rgb(205, 91, 69);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/* Route section */
|
|
116
|
+
|
|
117
|
+
.route .title a:hover {
|
|
118
|
+
text-decoration: none;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.route td {
|
|
122
|
+
vertical-align: top;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.route ul {
|
|
126
|
+
padding-left: 20px;
|
|
127
|
+
margin-top: 0;
|
|
128
|
+
margin-bottom: 0;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.route li {
|
|
132
|
+
/* list-style-type: none; */
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.route .constraint {
|
|
136
|
+
color: rgb(100, 100, 100);
|
|
137
|
+
font-size: smaller;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/* JSON highlighting */
|
|
141
|
+
|
|
142
|
+
.json_highlight .keyword {
|
|
143
|
+
font-weight: bold;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.json_highlight .numeric {
|
|
147
|
+
color: #099;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.json_highlight .key {
|
|
151
|
+
color: #000080;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.json_highlight .string {
|
|
155
|
+
color: #d14;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.json_highlight .comment {
|
|
159
|
+
color: rgb(236, 166, 18);
|
|
160
|
+
}
|