grape 0.2.6 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grape might be problematic. Click here for more details.

Files changed (50) hide show
  1. data/{CHANGELOG.markdown → CHANGELOG.md} +21 -1
  2. data/Gemfile +1 -0
  3. data/{README.markdown → README.md} +178 -125
  4. data/grape.gemspec +1 -1
  5. data/lib/grape.rb +25 -3
  6. data/lib/grape/api.rb +43 -20
  7. data/lib/grape/endpoint.rb +32 -13
  8. data/lib/grape/exceptions/base.rb +50 -1
  9. data/lib/grape/exceptions/invalid_formatter.rb +13 -0
  10. data/lib/grape/exceptions/invalid_versioner_option.rb +14 -0
  11. data/lib/grape/exceptions/invalid_with_option_for_represent.rb +15 -0
  12. data/lib/grape/exceptions/missing_mime_type.rb +14 -0
  13. data/lib/grape/exceptions/missing_option.rb +13 -0
  14. data/lib/grape/exceptions/missing_vendor_option.rb +13 -0
  15. data/lib/grape/exceptions/unknown_options.rb +14 -0
  16. data/lib/grape/exceptions/unknown_validator.rb +12 -0
  17. data/lib/grape/exceptions/{validation_error.rb → validation.rb} +3 -1
  18. data/lib/grape/formatter/xml.rb +2 -1
  19. data/lib/grape/locale/en.yml +20 -0
  20. data/lib/grape/middleware/base.rb +0 -5
  21. data/lib/grape/middleware/error.rb +1 -2
  22. data/lib/grape/middleware/formatter.rb +9 -5
  23. data/lib/grape/middleware/versioner.rb +1 -1
  24. data/lib/grape/middleware/versioner/header.rb +16 -6
  25. data/lib/grape/middleware/versioner/param.rb +1 -1
  26. data/lib/grape/middleware/versioner/path.rb +1 -1
  27. data/lib/grape/util/content_types.rb +0 -2
  28. data/lib/grape/validations.rb +7 -14
  29. data/lib/grape/validations/coerce.rb +2 -1
  30. data/lib/grape/validations/presence.rb +2 -1
  31. data/lib/grape/validations/regexp.rb +2 -1
  32. data/lib/grape/version.rb +1 -1
  33. data/spec/grape/api_spec.rb +150 -5
  34. data/spec/grape/endpoint_spec.rb +51 -157
  35. data/spec/grape/entity_spec.rb +142 -520
  36. data/spec/grape/exceptions/invalid_formatter_spec.rb +18 -0
  37. data/spec/grape/exceptions/invalid_versioner_option_spec.rb +18 -0
  38. data/spec/grape/exceptions/missing_mime_type_spec.rb +24 -0
  39. data/spec/grape/exceptions/missing_option_spec.rb +18 -0
  40. data/spec/grape/exceptions/unknown_options_spec.rb +18 -0
  41. data/spec/grape/exceptions/unknown_validator_spec.rb +18 -0
  42. data/spec/grape/middleware/formatter_spec.rb +40 -34
  43. data/spec/grape/middleware/versioner/header_spec.rb +78 -20
  44. data/spec/grape/middleware/versioner/path_spec.rb +12 -8
  45. data/spec/grape/validations/coerce_spec.rb +1 -0
  46. data/spec/grape/validations/presence_spec.rb +8 -8
  47. data/spec/grape/validations_spec.rb +26 -3
  48. data/spec/spec_helper.rb +3 -6
  49. metadata +44 -9
  50. data/lib/grape/entity.rb +0 -386
@@ -1,3 +1,23 @@
1
+ 0.3.0 (02/21/2013)
2
+ ==================
3
+
4
+ * [#294](https://github.com/intridea/grape/issues/294): Extracted `Grape::Entity` into a [grape-entity](https://github.com/agileanimal/grape-entity) gem - [@agileanimal](https://github.com/agileanimal).
5
+ * [#340](https://github.com/intridea/grape/pull/339), [#342](https://github.com/intridea/grape/pull/342): Added `:cascade` option to `version` to allow disabling of rack/mount cascade behavior - [@dieb](https://github.com/dieb).
6
+ * [#333](https://github.com/intridea/grape/pull/333): Added support for validation of arrays in `params` - [@flyerhzm](https://github.com/flyerhzm).
7
+ * [#306](https://github.com/intridea/grape/issues/306): Added I18n support for all Grape exceptions - [@niedhui](https://github.com/niedhui).
8
+ * [#309](https://github.com/intridea/grape/pull/309): Added XML support to the entity presenter - [@johnnyiller](https://github.com/johnnyiller), [@dblock](http://github.com/dblock).
9
+ * [#131](https://github.com/intridea/grape/issues/131): Added instructions for Grape API reloading in Rails - [@jyn](http://github.com/jyn), [@dblock](http://github.com/dblock).
10
+ * [#317](https://github.com/intridea/grape/issues/317): Added `headers` that returns a hash of parsed HTTP request headers - [@dblock](http://github.com/dblock).
11
+ * [#332](https://github.com/intridea/grape/pull/332): `Grape::Exceptions::Validation` now contains full nested parameter names - [@alovak](https://github.com/alovak).
12
+ * [#328](https://github.com/intridea/grape/issues/328): API version can now be specified as both String and Symbol - [@dblock](http://github.com/dblock).
13
+ * [#190](https://github.com/intridea/grape/issues/190): When you add a `GET` route for a resource, a route for the `HEAD` method will also be added automatically. You can disable this behavior with `do_not_route_head!` - [@dblock](http://github.com/dblock).
14
+ * Added `do_not_route_options!`, which disables the automatic creation of the `OPTIONS` route - [@dblock](http://github.com/dblock).
15
+ * [#309](https://github.com/intridea/grape/pull/309): An XML format API will return an error instead of returning a string representation of the response if the latter cannot be converted to XML - [@dblock](http://github.com/dblock).
16
+ * A formatter that raises an exception will cause the API to return a 500 error - [@dblock](http://github.com/dblock).
17
+ * [#322](https://github.com/intridea/grape/issues/322): When returning a 406 status, Grape will include the requested format or content-type in the response body - [@dblock](http://github.com/dblock).
18
+ * [#60](https://github.com/intridea/grape/issues/60): Fix: mounting of a Grape API onto a path - [@dblock](http://github.com/dblock).
19
+ * [#335](https://github.com/intridea/grape/pull/335): Fix: request body parameters from a `PATCH` request not available in `params` - [@FreakenK](http://github.com/FreakenK).
20
+
1
21
  0.2.6 (01/11/2013)
2
22
  ==================
3
23
 
@@ -77,7 +97,7 @@ Fixes
77
97
 
78
98
  * [#186](https://github.com/intridea/grape/issues/186): Fix: helpers allow multiple calls with modules and blocks - [@ppadron](https://github.com/ppadron).
79
99
  * [#188](https://github.com/intridea/grape/pull/188): Fix: multi-method routes append '(.:format)' only once - [@kainosnoema](https://github.com/kainosnoema).
80
- * [#64](https://github.com/intridea/grape/issues/64), [#180](https://github.com/intridea/grape/pull/180): Added support to get request bodies as parameters - [@bobbytables](https://github.com/bobbytables).
100
+ * [#64](https://github.com/intridea/grape/issues/64), [#180](https://github.com/intridea/grape/pull/180): Added support to `GET` request bodies as parameters - [@bobbytables](https://github.com/bobbytables).
81
101
  * [#175](https://github.com/intridea/grape/pull/175): Added support for API versioning based on a request parameter - [@jackcasey](https://github.com/jackcasey).
82
102
  * [#168](https://github.com/intridea/grape/pull/168): Fix: Formatter can parse symbol keys in the headers hash - [@netmask](https://github.com/netmask).
83
103
  * [#169](https://github.com/intridea/grape/pull/169): Silence multi_json deprecation warnings - [@whiteley](https://github.com/whiteley).
data/Gemfile CHANGED
@@ -13,4 +13,5 @@ group :development, :test do
13
13
  gem 'rspec'
14
14
  gem 'rack-test', "~> 0.6.2", :require => "rack/test"
15
15
  gem 'github-markup'
16
+ gem 'cookiejar'
16
17
  end
@@ -10,6 +10,11 @@ content negotiation, versioning and much more.
10
10
 
11
11
  [![Build Status](https://travis-ci.org/intridea/grape.png?branch=master)](http://travis-ci.org/intridea/grape)
12
12
 
13
+ ## Stable Release
14
+
15
+ You're reading the documentation for the next release of Grape, which should be 0.3.
16
+ The current stable release is [0.2.6](https://github.com/intridea/grape/blob/v0.2.6/README.markdown).
17
+
13
18
  ## Project Tracking
14
19
 
15
20
  * [Grape Google Group](http://groups.google.com/group/ruby-grape)
@@ -114,7 +119,7 @@ end
114
119
 
115
120
  ### Rack
116
121
 
117
- The above sample creates a Rack application that can be run from a rackup *config.ru* file
122
+ The above sample creates a Rack application that can be run from a rackup `config.ru` file
118
123
  with `rackup`:
119
124
 
120
125
  ```ruby
@@ -130,16 +135,24 @@ And would respond to the following routes:
130
135
  PUT /statuses/:id(.json)
131
136
  DELETE /statuses/:id(.json)
132
137
 
138
+ Grape will also automatically respond to HEAD and OPTIONS for all GET, and just OPTIONS for all other routes.
139
+
133
140
  ### Rails
134
141
 
135
- In a Rails application, modify *config/routes*:
142
+ Place API files into `app/api` and modify `application.rb`.
136
143
 
137
144
  ```ruby
138
- mount Twitter::API
145
+ config.paths.add "app/api", :glob => "**/*.rb"
146
+ config.autoload_paths += Dir["#{Rails.root}/app/api/*"]
139
147
  ```
140
148
 
141
- Note that when using Rails you will need to restart the server to pick up changes in your API classes
142
- (see [Issue 131](https://github.com/intridea/grape/issues/131)).
149
+ Modify `config/routes`:
150
+
151
+ ```ruby
152
+ mount Twitter::API => '/'
153
+ ```
154
+
155
+ See below for additional code that enables reloading of API changes in development.
143
156
 
144
157
  ### Modules
145
158
 
@@ -153,10 +166,28 @@ class Twitter::API < Grape::API
153
166
  end
154
167
  ```
155
168
 
169
+ You can also mount on a path, which is similar to using `prefix` inside the mounted API itself.
170
+
171
+ ```ruby
172
+ class Twitter::API < Grape::API
173
+ mount Twitter::APIv1 => '/v1'
174
+ end
175
+ ```
176
+
156
177
  ## Versioning
157
178
 
158
- There are three strategies in which clients can reach your API's endpoints: `:header`,
159
- `:path` and `:param`. The default strategy is `:path`.
179
+ There are three strategies in which clients can reach your API's endpoints: `:path`,
180
+ `:header` and `:param`. The default strategy is `:path`.
181
+
182
+ ### Path
183
+
184
+ ```ruby
185
+ version 'v1', :using => :path
186
+ ```
187
+
188
+ Using this versioning strategy, clients should pass the desired version in the URL.
189
+
190
+ curl -H http://localhost:9292/v1/statuses/public_timeline
160
191
 
161
192
  ### Header
162
193
 
@@ -173,16 +204,6 @@ supplied. This behavior is similar to routing in Rails. To circumvent this defau
173
204
  one could use the `:strict` option. When this option is set to `true`, a `406 Not Acceptable` error
174
205
  is returned when no correct `Accept` header is supplied.
175
206
 
176
- ### Path
177
-
178
- ```ruby
179
- version 'v1', :using => :path
180
- ```
181
-
182
- Using this versioning strategy, clients should pass the desired version in the URL.
183
-
184
- curl -H http://localhost:9292/v1/statuses/public_timeline
185
-
186
207
  ### Param
187
208
 
188
209
  ```ruby
@@ -202,6 +223,7 @@ version 'v1', :using => :param, :parameter => "v"
202
223
 
203
224
  curl -H http://localhost:9292/statuses/public_timeline?v=v1
204
225
 
226
+
205
227
  ## Describing Methods
206
228
 
207
229
  You can add a description to API methods and namespaces.
@@ -241,6 +263,22 @@ post '/statuses' do
241
263
  end
242
264
  ```
243
265
 
266
+ Multipart POSTs and PUTs are supported as well.
267
+
268
+ The request:
269
+
270
+ ```
271
+ curl --form image_file=image.jpg http://localhost:9292/upload
272
+ ```
273
+
274
+ The Grape endpoint:
275
+
276
+ ```ruby
277
+ post "upload" do
278
+ # file in params[:image_file]
279
+ end
280
+ ```
281
+
244
282
  ## Parameter Validation and Coercion
245
283
 
246
284
  You can define validations and coercion options for your parameters using a `params` block.
@@ -285,6 +323,9 @@ namespace :statuses do
285
323
  end
286
324
  ```
287
325
 
326
+ The `namespace` method has a number of aliases, including: `group`, `resource`,
327
+ `resources`, and `segment`. Use whichever reads the best for your API.
328
+
288
329
  ### Custom Validators
289
330
 
290
331
  ```ruby
@@ -339,22 +380,26 @@ end
339
380
 
340
381
  ## Headers
341
382
 
342
- Headers are available through the `header` helper or the `env` hash object.
383
+ Request headers are available through the `headers` helper or from `env` in their original form.
343
384
 
344
385
  ```ruby
345
386
  get do
346
- content_type = header['Content-type']
347
- # ...
387
+ error!('Unauthorized', 401) unless headers['Secret-Password'] == 'swordfish'
348
388
  end
349
389
  ```
350
390
 
351
391
  ```ruby
352
392
  get do
353
393
  error!('Unauthorized', 401) unless env['HTTP_SECRET_PASSWORD'] == 'swordfish'
354
- # ...
355
394
  end
356
395
  ```
357
396
 
397
+ You can set a response header with `header` inside an API.
398
+
399
+ ```ruby
400
+ header "X-Robots-Tag", "noindex"
401
+ ```
402
+
358
403
  ## Routes
359
404
 
360
405
  Optionally, you can define requirements for your named route parameters using regular
@@ -455,7 +500,23 @@ redirect "/statuses", :permanent => true
455
500
 
456
501
  ## Allowed Methods
457
502
 
458
- When you add a route for a resource, a route for the HTTP OPTIONS
503
+ When you add a `GET` route for a resource, a route for the `HEAD`
504
+ method will also be added automatically. You can disable this
505
+ behavior with `do_not_route_head!`.
506
+
507
+ ``` ruby
508
+ class API < Grape::API
509
+
510
+ do_not_route_head!
511
+
512
+ get '/example' do
513
+ # only responds to GET
514
+ end
515
+
516
+ end
517
+ ```
518
+
519
+ When you add a route for a resource, a route for the `OPTIONS`
459
520
  method will also be added. The response to an OPTIONS request will
460
521
  include an "Allow" header listing the supported methods.
461
522
 
@@ -486,6 +547,8 @@ curl -v -X OPTIONS http://localhost:3000/rt_count
486
547
  < Allow: OPTIONS, GET, PUT
487
548
  ```
488
549
 
550
+ You can disable this behavior with `do_not_route_options!`.
551
+
489
552
  If a request for a resource is made with an unsupported HTTP method, an
490
553
  HTTP 405 (Method Not Allowed) response will be returned.
491
554
 
@@ -593,6 +656,22 @@ class Twitter::API < Grape::API
593
656
  end
594
657
  ```
595
658
 
659
+ #### Rails 3.x
660
+
661
+ When mounted inside Rails 3.x, errors like "404 Not Found" or "406 Not Acceptable" will likely be
662
+ handled and rendered by Rails handlers. For instance, accessing a nonexistent route "/api/foo"
663
+ raises a 404, which inside rails will ultimately be translated to an `ActionController::RoutingError`,
664
+ which most likely will get rendered to a HTML error page.
665
+
666
+ Most APIs will enjoy avoiding Rails exceptions and have their own exceptions reaching the client.
667
+ In that case, the `:cascade` option can be set to `false` on the versioning definition.
668
+
669
+ ```ruby
670
+ version 'v1', :using => :header, :vendor => 'twitter', :cascade => false
671
+ ```
672
+
673
+ The `:cascade` option can also be used with the other versioning strategies (`:param` and `:path`).
674
+
596
675
  ## Logging
597
676
 
598
677
  `Grape::API` provides a `logger` method which by default will return an instance of the `Logger`
@@ -648,7 +727,7 @@ is determined by the request's extension, an explicit `format` parameter in the
648
727
  string, or `Accept` header.
649
728
 
650
729
  The following API will only respond to the JSON content-type and will not parse any other input than `application/json`,
651
- 'application/x-www-form-urlencoded', 'multipart/form-data', 'multipart/related' and 'multipart/mixed'. All other requests
730
+ `application/x-www-form-urlencoded`, `multipart/form-data`, `multipart/related` and `multipart/mixed`. All other requests
652
731
  will fail with an HTTP 406 error code.
653
732
 
654
733
  ```ruby
@@ -767,89 +846,34 @@ You can invoke the above API as follows.
767
846
  curl -X PUT -d 'data' 'http://localhost:9292/value' -H Content-Type:text/custom -v
768
847
  ```
769
848
 
770
- ## Reusable Responses with Entities
849
+ ## RESTful Model Representations
771
850
 
772
- Entities are a reusable means for converting Ruby objects to API responses.
773
- Entities can be used to conditionally include fields, nest other entities, and build
774
- ever larger responses, using inheritance.
851
+ Grape supports a range of ways to present your data with some help from a generic `present` method,
852
+ which accepts two arguments: the object to be presented and the options associated with it. The options
853
+ hash may include `:with`, which defines the entity to expose.
775
854
 
776
- ### Defining Entities
855
+ ### Grape Entities
777
856
 
778
- Entities inherit from Grape::Entity, and define a simple DSL. Exposures can use
779
- runtime options to determine which fields should be visible, these options are
780
- available to `:if`, `:unless`, and `:proc`. The option keys `:version` and `:collection`
781
- will always be defined. The `:version` key is defined as `api.version`. The
782
- `:collection` key is boolean, and defined as `true` if the object presented is an
783
- array.
857
+ Add the [grape-entity](https://github.com/agileanimal/grape-entity) gem to your Gemfile.
858
+ Please refer to the [grape-entity documentation](https://github.com/agileanimal/grape-entity/blob/master/README.markdown)
859
+ for more details.
784
860
 
785
- * `expose SYMBOLS`
786
- * define a list of fields which will always be exposed
787
- * `expose SYMBOLS, HASH`
788
- * HASH keys include `:if`, `:unless`, `:proc`, `:as`, `:using`, `:format_with`, `:documentation`
789
- * `:if` and `:unless` accept hashes (passed during runtime) or procs (arguments are object and options)
790
- * `expose SYMBOL, { :format_with => :formatter }`
791
- * expose a value, formatting it first
792
- * `:format_with` can only be applied to one exposure at a time
793
- * `expose SYMBOL, { :as => "alias" }`
794
- * Expose a value, changing its hash key from SYMBOL to alias
795
- * `:as` can only be applied to one exposure at a time
796
- * `expose SYMBOL BLOCK`
797
- * block arguments are object and options
798
- * expose the value returned by the block
799
- * block can only be applied to one exposure at a time
861
+ The following example exposes statuses.
800
862
 
801
863
  ```ruby
802
864
  module API
865
+
803
866
  module Entities
804
867
  class Status < Grape::Entity
805
868
  expose :user_name
806
869
  expose :text, :documentation => { :type => "string", :desc => "Status update text." }
807
870
  expose :ip, :if => { :type => :full }
808
871
  expose :user_type, user_id, :if => lambda{ |status, options| status.user.public? }
809
- expose :digest { |status, options| Digest::MD5.hexdigest(satus.txt) }
872
+ expose :digest { |status, options| Digest::MD5.hexdigest(status.txt) }
810
873
  expose :replies, :using => API::Status, :as => :replies
811
874
  end
812
875
  end
813
- end
814
-
815
- module API
816
- module Entities
817
- class StatusDetailed < API::Entities::Status
818
- expose :internal_id
819
- end
820
- end
821
- end
822
- ```
823
-
824
- #### Using the Exposure DSL
825
-
826
- Grape ships with a DSL to easily define entities within the context
827
- of an existing class:
828
-
829
- ```ruby
830
- class Status
831
- include Grape::Entity::DSL
832
-
833
- entity :text, :user_id do
834
- expose :detailed, if: :conditional
835
- end
836
- end
837
- ```
838
-
839
- The above will automatically create a `Status::Entity` class and define properties on it according
840
- to the same rules as above. If you only want to define simple exposures you don't have to supply
841
- a block and can instead simply supply a list of comma-separated symbols.
842
-
843
- ### Using Entities
844
876
 
845
- Once an entity is defined, it can be used within endpoints, by calling `present`. The `present`
846
- method accepts two arguments, the object to be presented and the options associated with it. The
847
- options hash must always include `:with`, which defines the entity to expose.
848
-
849
- If the entity includes documentation it can be included in an endpoint's description.
850
-
851
- ```ruby
852
- module API
853
877
  class Statuses < Grape::API
854
878
  version 'v1'
855
879
 
@@ -865,8 +889,6 @@ module API
865
889
  end
866
890
  ```
867
891
 
868
- ### Entity Organization
869
-
870
892
  In addition to separately organizing entities, it may be useful to put them as namespaced
871
893
  classes underneath the model they represent.
872
894
 
@@ -883,53 +905,44 @@ end
883
905
  ```
884
906
 
885
907
  If you organize your entities this way, Grape will automatically detect the `Entity` class and
886
- use it to present your models. In this example, if you added `present User.new` to your endpoint,
887
- Grape would automatically detect that there is a `Status::Entity` class and use that as the
908
+ use it to present your models. In this example, if you added `present Status.new` to your endpoint,
909
+ Grape will automatically detect that there is a `Status::Entity` class and use that as the
888
910
  representative entity. This can still be overridden by using the `:with` option or an explicit
889
911
  `represents` call.
890
912
 
891
- ### Caveats
913
+ ### Hypermedia
914
+
915
+ You can use any Hypermedia representer, including [Roar](https://github.com/apotonick/roar).
916
+ Roar renders JSON and works with the built-in Grape JSON formatter. Add `Roar::Representer::JSON`
917
+ into your models or call `to_json` explicitly in your API implementation.
918
+
919
+ ### Rabl
892
920
 
893
- Entities with duplicate exposure names and conditions will silently overwrite one another.
894
- In the following example, when `object.check` equals "foo", only `field_a` will be exposed.
895
- However, when `object.check` equals "bar" both `field_b` and `foo` will be exposed.
921
+ You can use [Rabl](https://github.com/nesquena/rabl) templates with the help of the
922
+ [grape-rabl](https://github.com/LTe/grape-rabl) gem, which defines a custom Grape Rabl
923
+ formatter.
924
+
925
+ ## Authentication
926
+
927
+ ### Basic and Digest Auth
928
+
929
+ Grape has built-in Basic and Digest authentication.
896
930
 
897
931
  ```ruby
898
- module API
899
- module Entities
900
- class Status < Grape::Entity
901
- expose :field_a, :foo, :if => lambda { |object, options| object.check == "foo" }
902
- expose :field_b, :foo, :if => lambda { |object, options| object.check == "bar" }
903
- end
904
- end
932
+ http_basic do |username, password|
933
+ # verify user's password here
934
+ { 'test' => 'password1' }[username] == password
905
935
  end
906
936
  ```
907
937
 
908
- This can be problematic, when you have mixed collections. Using `respond_to?` is safer.
909
-
910
938
  ```ruby
911
- module API
912
- module Entities
913
- class Status < Grape::Entity
914
- expose :field_a, :if => lambda { |object, options| object.check == "foo" }
915
- expose :field_b, :if => lambda { |object, options| object.check == "bar" }
916
- expose :foo, :if => lambda { |object, options| object.respond_to?(:foo) }
917
- end
918
- end
939
+ http_digest({ :realm => 'Test Api', :opaque => 'app secret' }) do |username|
940
+ # lookup the user's password here
941
+ { 'user1' => 'password1' }[username]
919
942
  end
920
943
  ```
921
944
 
922
- ## Hypermedia and other RESTful Representations
923
-
924
- Although Grape ships with its own entity support, it's also possible to use it with other frameworks and renderers.
925
-
926
- ### Hypermedia
927
-
928
- Use [Roar](https://github.com/apotonick/roar). Include `Roar::Representer::JSON` in your models or call `to_json` explicitly on representers in your API.
929
-
930
- ### Rabl
931
-
932
- [Rabl](https://github.com/nesquena/rabl) is supported via the [grape-rabl](https://github.com/LTe/grape-rabl) gem.
945
+ Use [warden-oauth2](https://github.com/opperator/warden-oauth2) or [rack-oauth2](https://github.com/nov/rack-oauth2) for OAuth2 support.
933
946
 
934
947
  ## Describing and Inspecting an API
935
948
 
@@ -981,6 +994,16 @@ class ApiLogger < Grape::Middleware::Base
981
994
  end
982
995
  ```
983
996
 
997
+ ## Before and After
998
+
999
+ Execute a block before or after every API call with `before` and `after`.
1000
+
1001
+ ```ruby
1002
+ before do
1003
+ header "X-Robots-Tag", "noindex"
1004
+ end
1005
+ ```
1006
+
984
1007
  ## Anchoring
985
1008
 
986
1009
  Grape by default anchors all request paths, which means that the request URL
@@ -1080,6 +1103,36 @@ RSpec.configure do |config|
1080
1103
  }
1081
1104
  end
1082
1105
  ```
1106
+
1107
+ ## Reloading API Changes in Development
1108
+
1109
+ ### Rails 3.x
1110
+
1111
+ Add API paths to `config/application.rb`.
1112
+
1113
+ ```ruby
1114
+ # Auto-load API and its subdirectories
1115
+ config.paths.add "app/api", :glob => "**/*.rb"
1116
+ config.autoload_paths += Dir["#{Rails.root}/app/api/*"]
1117
+ ```
1118
+
1119
+ Create `config/initializers/reload_api.rb`.
1120
+
1121
+ ```ruby
1122
+ if Rails.env.development?
1123
+ api_files = Dir["#{Rails.root}/app/api/**/*.rb"]
1124
+ api_reloader = ActiveSupport::FileUpdateChecker.new(api_files) do
1125
+ Rails.application.reload_routes!
1126
+ end
1127
+ ActionDispatch::Callbacks.to_prepare do
1128
+ api_reloader.execute_if_updated
1129
+ end
1130
+ end
1131
+ ```
1132
+
1133
+ See [StackOverflow #3282655](http://stackoverflow.com/questions/3282655/ruby-on-rails-3-reload-lib-directory-for-each-request/4368838#4368838) for more information.
1134
+
1135
+
1083
1136
  ## Performance Monitoring
1084
1137
 
1085
1138
  Grape integrates with NewRelic via the [newrelic-grape](https://github.com/flyerhzm/newrelic-grape) gem.