grape 0.6.0 → 0.6.1
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.
- checksums.yaml +8 -8
- data/.rubocop.yml +65 -0
- data/.travis.yml +4 -0
- data/CHANGELOG.md +17 -1
- data/Gemfile +1 -0
- data/README.md +16 -8
- data/RELEASING.md +105 -0
- data/grape.gemspec +1 -1
- data/lib/grape.rb +1 -0
- data/lib/grape/api.rb +88 -54
- data/lib/grape/cookies.rb +4 -6
- data/lib/grape/endpoint.rb +81 -69
- data/lib/grape/error_formatter/base.rb +5 -4
- data/lib/grape/error_formatter/json.rb +3 -3
- data/lib/grape/error_formatter/txt.rb +1 -1
- data/lib/grape/error_formatter/xml.rb +4 -4
- data/lib/grape/exceptions/base.rb +7 -7
- data/lib/grape/exceptions/incompatible_option_values.rb +13 -0
- data/lib/grape/exceptions/invalid_formatter.rb +1 -1
- data/lib/grape/exceptions/invalid_versioner_option.rb +1 -1
- data/lib/grape/exceptions/invalid_with_option_for_represent.rb +1 -4
- data/lib/grape/exceptions/missing_mime_type.rb +1 -1
- data/lib/grape/exceptions/missing_option.rb +1 -1
- data/lib/grape/exceptions/missing_vendor_option.rb +1 -1
- data/lib/grape/exceptions/unknown_options.rb +1 -1
- data/lib/grape/exceptions/unknown_validator.rb +1 -1
- data/lib/grape/exceptions/validation.rb +2 -2
- data/lib/grape/exceptions/validation_errors.rb +1 -1
- data/lib/grape/formatter/base.rb +5 -4
- data/lib/grape/formatter/serializable_hash.rb +7 -6
- data/lib/grape/http/request.rb +2 -2
- data/lib/grape/locale/en.yml +2 -0
- data/lib/grape/middleware/auth/base.rb +3 -3
- data/lib/grape/middleware/auth/basic.rb +1 -1
- data/lib/grape/middleware/auth/oauth2.rb +18 -20
- data/lib/grape/middleware/base.rb +1 -1
- data/lib/grape/middleware/error.rb +19 -19
- data/lib/grape/middleware/filter.rb +3 -3
- data/lib/grape/middleware/formatter.rb +29 -23
- data/lib/grape/middleware/versioner.rb +1 -1
- data/lib/grape/middleware/versioner/accept_version_header.rb +8 -6
- data/lib/grape/middleware/versioner/header.rb +16 -14
- data/lib/grape/middleware/versioner/param.rb +7 -7
- data/lib/grape/middleware/versioner/path.rb +7 -9
- data/lib/grape/parser/base.rb +3 -2
- data/lib/grape/path.rb +1 -1
- data/lib/grape/route.rb +6 -4
- data/lib/grape/util/content_types.rb +2 -1
- data/lib/grape/util/deep_merge.rb +5 -5
- data/lib/grape/util/hash_stack.rb +2 -2
- data/lib/grape/validations.rb +34 -30
- data/lib/grape/validations/coerce.rb +6 -5
- data/lib/grape/validations/default.rb +0 -1
- data/lib/grape/validations/presence.rb +1 -1
- data/lib/grape/validations/regexp.rb +2 -2
- data/lib/grape/validations/values.rb +16 -0
- data/lib/grape/version.rb +1 -1
- data/spec/grape/api_spec.rb +229 -210
- data/spec/grape/endpoint_spec.rb +56 -54
- data/spec/grape/entity_spec.rb +31 -33
- data/spec/grape/exceptions/missing_mime_type_spec.rb +3 -9
- data/spec/grape/middleware/auth/basic_spec.rb +8 -8
- data/spec/grape/middleware/auth/digest_spec.rb +5 -5
- data/spec/grape/middleware/auth/oauth2_spec.rb +23 -23
- data/spec/grape/middleware/base_spec.rb +6 -6
- data/spec/grape/middleware/error_spec.rb +11 -15
- data/spec/grape/middleware/exception_spec.rb +45 -25
- data/spec/grape/middleware/formatter_spec.rb +56 -45
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +25 -25
- data/spec/grape/middleware/versioner/header_spec.rb +54 -54
- data/spec/grape/middleware/versioner/param_spec.rb +17 -18
- data/spec/grape/middleware/versioner/path_spec.rb +6 -6
- data/spec/grape/middleware/versioner_spec.rb +1 -1
- data/spec/grape/util/hash_stack_spec.rb +26 -27
- data/spec/grape/validations/coerce_spec.rb +39 -34
- data/spec/grape/validations/default_spec.rb +12 -13
- data/spec/grape/validations/presence_spec.rb +18 -22
- data/spec/grape/validations/regexp_spec.rb +9 -9
- data/spec/grape/validations/values_spec.rb +64 -0
- data/spec/grape/validations_spec.rb +127 -70
- data/spec/shared/versioning_examples.rb +5 -5
- data/spec/support/basic_auth_encode_helpers.rb +0 -1
- data/spec/support/versioned_helpers.rb +5 -6
- metadata +10 -4
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
N2JkMzEwZGIyN2M4ZWVkMjczNmU1OTZiNTQzYTA3Yjc1YWI1MzRiNw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ODE0MmI1YjY3YjZlNjdhOGY0ZGI1OTdjMWRhYmI3N2JiZjJmNWMwYg==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NWYxMGEyMWE0NWE4ZTlkMjczMmY3ZjA1NGUwZjNhZmJlYjk3MGQ5NTE0NDk3
|
10
|
+
OGUyOWU5YmVhNzMwMWJkOTIxYjgwZmU0ODk1YWU4Yzc1ZTdkMWY4NTc0MDlh
|
11
|
+
ODQ4NjczZWRhMGVmMmQ1MDg3Njk5MjBjMTk5N2VjYmM0Y2ZiZDE=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
OTI1ZDU2ZDViNjc2YWE4MTczMThmN2I5ZGYwZGZlYmE0YjZlMDI3NjVlNTE5
|
14
|
+
NjcwOTRkNTg2NTgwODFhMTg3YjZkM2Y3NzYwYzkwNTYxMGEzMzU2NDBiYzBk
|
15
|
+
ZGJlYTRmMDEwNGJkNDc3YzNiMmUyM2IyMDUwMGM3MGFhMDhiYTg=
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
AllCops:
|
2
|
+
Excludes:
|
3
|
+
- vendor/**
|
4
|
+
|
5
|
+
LineLength:
|
6
|
+
Enabled: false
|
7
|
+
|
8
|
+
MethodLength:
|
9
|
+
Enabled: false
|
10
|
+
|
11
|
+
ClassLength:
|
12
|
+
Enabled: false
|
13
|
+
|
14
|
+
Documentation:
|
15
|
+
# don't require classes to be documented
|
16
|
+
Enabled: false
|
17
|
+
|
18
|
+
CollectionMethods:
|
19
|
+
# don't prefer map to collect, recuce to inject
|
20
|
+
Enabled: false
|
21
|
+
|
22
|
+
Encoding:
|
23
|
+
# no need to always specify encoding
|
24
|
+
Enabled: false
|
25
|
+
|
26
|
+
HashMethods:
|
27
|
+
# key? instead of has_key?
|
28
|
+
# value? instead of has_value?
|
29
|
+
Enabled: false
|
30
|
+
|
31
|
+
StringLiterals:
|
32
|
+
# use single or double-quoted strings, as you please
|
33
|
+
Enabled: false
|
34
|
+
|
35
|
+
Void:
|
36
|
+
# == operator used in void context in specs
|
37
|
+
Enabled: false
|
38
|
+
|
39
|
+
SignalException:
|
40
|
+
# prefer raise to fail
|
41
|
+
EnforcedStyle: only_raise
|
42
|
+
|
43
|
+
RaiseArgs:
|
44
|
+
# don't care for what kind of raise
|
45
|
+
Enabled: false
|
46
|
+
|
47
|
+
PerlBackrefs:
|
48
|
+
# TODO: regular expression matching with $1, $2, etc.
|
49
|
+
Enabled: false
|
50
|
+
|
51
|
+
BlockNesting:
|
52
|
+
# TODO: fix too much nesting
|
53
|
+
Max: 4
|
54
|
+
|
55
|
+
Lambda:
|
56
|
+
# TODO: replace all lambda with -> or Proc
|
57
|
+
Enabled: false
|
58
|
+
|
59
|
+
Blocks:
|
60
|
+
# allow multi-line blocks like expect { }
|
61
|
+
Enabled: false
|
62
|
+
|
63
|
+
WordArray:
|
64
|
+
# %w vs. [ '', ... ]
|
65
|
+
Enabled: false
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,20 @@
|
|
1
|
+
0.6.1
|
2
|
+
=====
|
3
|
+
|
4
|
+
#### Features
|
5
|
+
|
6
|
+
* [#475](https://github.com/intridea/grape/pull/475): Added support for the `:jsonapi`, `application/vnd.api+json` media type registered at http://jsonapi.org - [@bcm](https://github.com/bcm).
|
7
|
+
* [#471](https://github.com/intridea/grape/issues/471): Added parameter validator for a list of allowed values - [@vickychijwani](https://github.com/vickychijwani).
|
8
|
+
* [#488](https://github.com/intridea/grape/issues/488): Upgraded to Virtus 1.0 - [@dblock](https://github.com/dblock).
|
9
|
+
|
10
|
+
#### Fixes
|
11
|
+
|
12
|
+
* [#477](https://github.com/intridea/grape/pull/477): Fixed `default_error_formatter` which takes a format symbol - [@vad4msiu](https://github.com/vad4msiu).
|
13
|
+
|
14
|
+
#### Development
|
15
|
+
|
16
|
+
* Implemented Rubocop, a Ruby code static code analyzer - [@dblock](https://github.com/dblock).
|
17
|
+
|
1
18
|
0.6.0 (9/16/2013)
|
2
19
|
=================
|
3
20
|
|
@@ -12,7 +29,6 @@
|
|
12
29
|
* [#443](https://github.com/intridea/grape/pull/443): Let `requires` and `optional` take blocks that initialize new scopes - [@asross](https://github.com/asross).
|
13
30
|
* [#452](https://github.com/intridea/grape/pull/452): Added `with` as a hash option to specify handlers for `rescue_from` and `error_formatter` [@robertopedroso](https://github.com/robertopedroso).
|
14
31
|
* [#433](https://github.com/intridea/grape/issues/433), [#462](https://github.com/intridea/grape/issues/462): API change: validation errors are now collected and `Grape::Exceptions::ValidationErrors` is raised - [@stevschmid](https://github.com/stevschmid).
|
15
|
-
* Your contribution here.
|
16
32
|
|
17
33
|
#### Fixes
|
18
34
|
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -12,7 +12,7 @@ content negotiation, versioning and much more.
|
|
12
12
|
|
13
13
|
## Stable Release
|
14
14
|
|
15
|
-
You're reading the documentation for the stable release of Grape, 0.6.
|
15
|
+
You're reading the documentation for the stable release of Grape, 0.6.1.
|
16
16
|
|
17
17
|
## Project Resources
|
18
18
|
|
@@ -334,7 +334,7 @@ params do
|
|
334
334
|
requires :url
|
335
335
|
end
|
336
336
|
optional :audio do
|
337
|
-
requires :mp3
|
337
|
+
requires :format, type: Symbol, values: [:mp3, :wav, :aac, :ogg], default: :mp3
|
338
338
|
end
|
339
339
|
end
|
340
340
|
put ':id' do
|
@@ -353,6 +353,14 @@ params do
|
|
353
353
|
end
|
354
354
|
```
|
355
355
|
|
356
|
+
Parameters can be restricted to a specific set of values with the `:values` option.
|
357
|
+
|
358
|
+
```ruby
|
359
|
+
params do
|
360
|
+
requires :status, type: Symbol, values: [:not_started, :processing, :done]
|
361
|
+
end
|
362
|
+
```
|
363
|
+
|
356
364
|
Parameters can be nested using `group` or by calling `requires` or `optional` with a block.
|
357
365
|
In the above example, this means `params[:media][:url]` is required along with `params[:id]`,
|
358
366
|
and `params[:audio][:mp3]` is required only if `params[:audio]` is present.
|
@@ -706,13 +714,13 @@ class Twitter::API < Grape::API
|
|
706
714
|
end
|
707
715
|
```
|
708
716
|
|
709
|
-
You can rescue all exceptions with a code block. The `
|
717
|
+
You can rescue all exceptions with a code block. The `error_response` wrapper
|
710
718
|
automatically sets the default error code and content-type.
|
711
719
|
|
712
720
|
```ruby
|
713
721
|
class Twitter::API < Grape::API
|
714
722
|
rescue_from :all do |e|
|
715
|
-
|
723
|
+
error_response({ message: "rescued from #{e.class.name}" })
|
716
724
|
end
|
717
725
|
end
|
718
726
|
```
|
@@ -871,7 +879,7 @@ end
|
|
871
879
|
|
872
880
|
Built-in formats are the following.
|
873
881
|
|
874
|
-
* `:json`: use object's `to_json` when available, otherwise call `MultiJson.dump`
|
882
|
+
* `:json` and `:jsonapi`: use object's `to_json` when available, otherwise call `MultiJson.dump`
|
875
883
|
* `:xml`: use object's `to_xml` when available, usually via `MultiXml`, otherwise call `to_s`
|
876
884
|
* `:txt`: use object's `to_txt` when available, otherwise `to_s`
|
877
885
|
* `:serializable_hash`: use object's `serializable_hash` when available, otherwise fallback to `:json`
|
@@ -896,7 +904,7 @@ The order for choosing the format is the following.
|
|
896
904
|
|
897
905
|
### JSONP
|
898
906
|
|
899
|
-
Grape
|
907
|
+
Grape supports JSONP via [Rack::JSONP](https://github.com/rack/rack-contrib), part of the
|
900
908
|
[rack-contrib](https://github.com/rack/rack-contrib) gem. Add `rack-contrib` to your `Gemfile`.
|
901
909
|
|
902
910
|
```ruby
|
@@ -993,7 +1001,7 @@ hash may include `:with`, which defines the entity to expose.
|
|
993
1001
|
### Grape Entities
|
994
1002
|
|
995
1003
|
Add the [grape-entity](https://github.com/intridea/grape-entity) gem to your Gemfile.
|
996
|
-
Please refer to the [grape-entity documentation](https://github.com/intridea/grape-entity/blob/master/README.
|
1004
|
+
Please refer to the [grape-entity documentation](https://github.com/intridea/grape-entity/blob/master/README.md)
|
997
1005
|
for more details.
|
998
1006
|
|
999
1007
|
The following example exposes statuses.
|
@@ -1006,7 +1014,7 @@ module API
|
|
1006
1014
|
expose :user_name
|
1007
1015
|
expose :text, documentation: { type: "string", desc: "Status update text." }
|
1008
1016
|
expose :ip, if: { type: :full }
|
1009
|
-
expose :user_type, user_id, if: lambda{ |status, options| status.user.public? }
|
1017
|
+
expose :user_type, user_id, if: lambda { |status, options| status.user.public? }
|
1010
1018
|
expose :digest { |status, options| Digest::MD5.hexdigest(status.txt) }
|
1011
1019
|
expose :replies, using: API::Status, as: :replies
|
1012
1020
|
end
|
data/RELEASING.md
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
Releasing Grape
|
2
|
+
===============
|
3
|
+
|
4
|
+
There're no particular rules about when to release Grape. Release bug fixes frequenty, features not so frequently and breaking API changes rarely.
|
5
|
+
|
6
|
+
### Release
|
7
|
+
|
8
|
+
Run tests, check that all tests succeed locally.
|
9
|
+
|
10
|
+
```
|
11
|
+
bundle install
|
12
|
+
rake
|
13
|
+
```
|
14
|
+
|
15
|
+
Check that the last build succeeded in [Travis CI](https://travis-ci.org/intridea/grape) for all supported platforms.
|
16
|
+
|
17
|
+
Those with r/w permissions to the [master Intridea repository](https://github.com/intridea/grape) generally have large Grape-based projects. Point one to Grape HEAD and run all your API tests to catch any obvious regressions.
|
18
|
+
|
19
|
+
```
|
20
|
+
gem grape, github: 'intridea/grape'
|
21
|
+
```
|
22
|
+
|
23
|
+
Increment the version, modify [lib/grape/version.rb](lib/grape/version.rb).
|
24
|
+
|
25
|
+
* Increment the third number if the release has bug fixes and/or very minor features, only (eg. change `0.5.1` to `0.5.2`).
|
26
|
+
* Increment the second number if the release contains major features or breaking API changes (eg. change `0.5.1` to `0.6.0`).
|
27
|
+
|
28
|
+
Modify the "Stable Release" section in [README.md](README.md). Change the text to reflect that this is going to be the documentation for a stable release. Remove references to the previous release of Grape. Keep the file open, you'll have to undo this change after the release.
|
29
|
+
|
30
|
+
```
|
31
|
+
## Stable Release
|
32
|
+
|
33
|
+
You're reading the documentation for the stable release of Grape, 0.6.0.
|
34
|
+
```
|
35
|
+
|
36
|
+
Change "Next Release" in [CHANGELOG.md](CHANGELOG.md) to the new version.
|
37
|
+
|
38
|
+
```
|
39
|
+
0.6.0 (9/16/2013)
|
40
|
+
=================
|
41
|
+
```
|
42
|
+
|
43
|
+
Remove the line with "Your contribution here.", since there will be no more contributions to this release.
|
44
|
+
|
45
|
+
Commit your changes.
|
46
|
+
|
47
|
+
```
|
48
|
+
git add README.md CHANGELOG.md lib/grape/version.rb
|
49
|
+
git commit -m "Preparing for release, 0.6.0."
|
50
|
+
git push origin master
|
51
|
+
```
|
52
|
+
|
53
|
+
Release.
|
54
|
+
|
55
|
+
```
|
56
|
+
$ rake release
|
57
|
+
|
58
|
+
grape 0.6.0 built to pkg/grape-0.6.0.gem.
|
59
|
+
Tagged v0.6.0.
|
60
|
+
Pushed git commits and tags.
|
61
|
+
Pushed grape 0.6.0 to rubygems.org.
|
62
|
+
```
|
63
|
+
|
64
|
+
### Prepare for the Next Version
|
65
|
+
|
66
|
+
Modify the "Stable Release" section in [README.md](README.md). Change the text to reflect that this is going to be the next release.
|
67
|
+
|
68
|
+
```
|
69
|
+
## Stable Release
|
70
|
+
|
71
|
+
You're reading the documentation for the next release of Grape, which should be 0.6.1.
|
72
|
+
The current stable release is [0.6.0](https://github.com/intridea/grape/blob/v0.6.0/README.md).
|
73
|
+
```
|
74
|
+
|
75
|
+
Add the next release to [CHANGELOG.md](CHANGELOG.md).
|
76
|
+
|
77
|
+
```
|
78
|
+
Next Release
|
79
|
+
============
|
80
|
+
|
81
|
+
* Your contribution here.
|
82
|
+
```
|
83
|
+
|
84
|
+
Comit your changes.
|
85
|
+
|
86
|
+
```
|
87
|
+
git add CHANGELOG.md README.md
|
88
|
+
git commit -m "Preparing for next release."
|
89
|
+
git push origin master
|
90
|
+
```
|
91
|
+
|
92
|
+
### Make an Announcement
|
93
|
+
|
94
|
+
Make an announcement on the [ruby-grape@googlegroups.com](mailto:ruby-grape@googlegroups.com) mailing list. The general format is as follows.
|
95
|
+
|
96
|
+
```
|
97
|
+
Grape 0.6.0 has been released.
|
98
|
+
|
99
|
+
There were 8 contributors to this release, not counting documentation.
|
100
|
+
|
101
|
+
Please note the breaking API change in ...
|
102
|
+
|
103
|
+
[copy/paste CHANGELOG here]
|
104
|
+
|
105
|
+
```
|
data/grape.gemspec
CHANGED
@@ -21,7 +21,7 @@ Gem::Specification.new do |s|
|
|
21
21
|
s.add_runtime_dependency 'multi_json', '>= 1.3.2'
|
22
22
|
s.add_runtime_dependency 'multi_xml', '>= 0.5.2'
|
23
23
|
s.add_runtime_dependency 'hashie', '>= 1.2.0'
|
24
|
-
s.add_runtime_dependency 'virtus'
|
24
|
+
s.add_runtime_dependency 'virtus', '>= 1.0.0'
|
25
25
|
s.add_runtime_dependency 'builder'
|
26
26
|
|
27
27
|
s.add_development_dependency 'grape-entity', '>= 0.2.0'
|
data/lib/grape.rb
CHANGED
@@ -44,6 +44,7 @@ module Grape
|
|
44
44
|
autoload :UnknownValidator, 'grape/exceptions/unknown_validator'
|
45
45
|
autoload :UnknownOptions, 'grape/exceptions/unknown_options'
|
46
46
|
autoload :InvalidWithOptionForRepresent, 'grape/exceptions/invalid_with_option_for_represent'
|
47
|
+
autoload :IncompatibleOptionValues, 'grape/exceptions/incompatible_option_values'
|
47
48
|
end
|
48
49
|
|
49
50
|
module ErrorFormatter
|
data/lib/grape/api.rb
CHANGED
@@ -26,7 +26,7 @@ module Grape
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def compile
|
29
|
-
@instance =
|
29
|
+
@instance = new
|
30
30
|
end
|
31
31
|
|
32
32
|
def change!
|
@@ -81,12 +81,12 @@ module Grape
|
|
81
81
|
# version 'v2'
|
82
82
|
#
|
83
83
|
# get '/main' do
|
84
|
-
# {:
|
84
|
+
# {some: 'data'}
|
85
85
|
# end
|
86
86
|
#
|
87
87
|
# version 'v1' do
|
88
88
|
# get '/main' do
|
89
|
-
# {:
|
89
|
+
# {legacy: 'data'}
|
90
90
|
# end
|
91
91
|
# end
|
92
92
|
# end
|
@@ -95,7 +95,7 @@ module Grape
|
|
95
95
|
if args.any?
|
96
96
|
options = args.pop if args.last.is_a? Hash
|
97
97
|
options ||= {}
|
98
|
-
options = {:
|
98
|
+
options = { using: :path }.merge(options)
|
99
99
|
|
100
100
|
raise Grape::Exceptions::MissingVendorOption.new if options[:using] == :header && !options.has_key?(:vendor)
|
101
101
|
|
@@ -111,7 +111,7 @@ module Grape
|
|
111
111
|
|
112
112
|
# Add a description to the next namespace or function.
|
113
113
|
def desc(description, options = {})
|
114
|
-
@last_description = options.merge(:
|
114
|
+
@last_description = options.merge(description: description)
|
115
115
|
end
|
116
116
|
|
117
117
|
# Specify the default format for the API's serializers.
|
@@ -147,8 +147,13 @@ module Grape
|
|
147
147
|
end
|
148
148
|
|
149
149
|
# Specify a default error formatter.
|
150
|
-
def default_error_formatter(
|
151
|
-
|
150
|
+
def default_error_formatter(new_formatter_name = nil)
|
151
|
+
if new_formatter_name
|
152
|
+
new_formatter = Grape::ErrorFormatter::Base.formatter_for(new_formatter_name, {})
|
153
|
+
set(:default_error_formatter, new_formatter)
|
154
|
+
else
|
155
|
+
settings[:default_error_formatter]
|
156
|
+
end
|
152
157
|
end
|
153
158
|
|
154
159
|
def error_formatter(format, options)
|
@@ -204,9 +209,7 @@ module Grape
|
|
204
209
|
end
|
205
210
|
|
206
211
|
options = args.last.is_a?(Hash) ? args.pop : {}
|
207
|
-
if options.has_key?(:with)
|
208
|
-
handler ||= proc { options[:with] }
|
209
|
-
end
|
212
|
+
handler ||= proc { options[:with] } if options.has_key?(:with)
|
210
213
|
|
211
214
|
if handler
|
212
215
|
args.each do |arg|
|
@@ -215,8 +218,12 @@ module Grape
|
|
215
218
|
end
|
216
219
|
|
217
220
|
imbue(:rescue_options, options)
|
218
|
-
|
219
|
-
|
221
|
+
|
222
|
+
if args.include?(:all)
|
223
|
+
set(:rescue_all, true)
|
224
|
+
else
|
225
|
+
imbue(:rescued_errors, args)
|
226
|
+
end
|
220
227
|
end
|
221
228
|
|
222
229
|
# Allows you to specify a default representation entity for a
|
@@ -225,10 +232,10 @@ module Grape
|
|
225
232
|
#
|
226
233
|
# @example
|
227
234
|
# class ExampleAPI < Grape::API
|
228
|
-
# represent User, :
|
235
|
+
# represent User, with: Entity::User
|
229
236
|
#
|
230
237
|
# get '/me' do
|
231
|
-
# present current_user # :
|
238
|
+
# present current_user # with: Entity::User is assumed
|
232
239
|
# end
|
233
240
|
# end
|
234
241
|
#
|
@@ -271,7 +278,7 @@ module Grape
|
|
271
278
|
include new_mod
|
272
279
|
end
|
273
280
|
end
|
274
|
-
mod.class_eval
|
281
|
+
mod.class_eval(&block) if block_given?
|
275
282
|
set(:helpers, mod)
|
276
283
|
else
|
277
284
|
mod = Module.new
|
@@ -287,7 +294,7 @@ module Grape
|
|
287
294
|
# only `:http_basic`, `:http_digest` and `:oauth2` are supported.
|
288
295
|
def auth(type = nil, options = {}, &block)
|
289
296
|
if type
|
290
|
-
set(:auth, {:
|
297
|
+
set(:auth, { type: type.to_sym, proc: block }.merge(options))
|
291
298
|
else
|
292
299
|
settings[:auth]
|
293
300
|
end
|
@@ -313,14 +320,14 @@ module Grape
|
|
313
320
|
mounts.each_pair do |app, path|
|
314
321
|
if app.respond_to?(:inherit_settings, true)
|
315
322
|
app_settings = settings.clone
|
316
|
-
mount_path = Rack::Mount::Utils.normalize_path([
|
323
|
+
mount_path = Rack::Mount::Utils.normalize_path([settings[:mount_path], path].compact.join("/"))
|
317
324
|
app_settings.set :mount_path, mount_path
|
318
325
|
app.inherit_settings(app_settings)
|
319
326
|
end
|
320
327
|
endpoints << Grape::Endpoint.new(settings.clone, {
|
321
|
-
:
|
322
|
-
:
|
323
|
-
:
|
328
|
+
method: :any,
|
329
|
+
path: path,
|
330
|
+
app: app
|
324
331
|
})
|
325
332
|
end
|
326
333
|
end
|
@@ -334,14 +341,14 @@ module Grape
|
|
334
341
|
# @example Defining a basic route.
|
335
342
|
# class MyAPI < Grape::API
|
336
343
|
# route(:any, '/hello') do
|
337
|
-
# {:
|
344
|
+
# {hello: 'world'}
|
338
345
|
# end
|
339
346
|
# end
|
340
347
|
def route(methods, paths = ['/'], route_options = {}, &block)
|
341
348
|
endpoint_options = {
|
342
|
-
:
|
343
|
-
:
|
344
|
-
:
|
349
|
+
method: methods,
|
350
|
+
path: paths,
|
351
|
+
route_options: (@namespace_description || {}).deep_merge(@last_description || {}).deep_merge(route_options || {})
|
345
352
|
}
|
346
353
|
endpoints << Grape::Endpoint.new(settings.clone, endpoint_options, &block)
|
347
354
|
|
@@ -361,13 +368,33 @@ module Grape
|
|
361
368
|
imbue(:afters, [block])
|
362
369
|
end
|
363
370
|
|
364
|
-
def get(paths = ['/'], options = {}, &block)
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
def
|
369
|
-
|
370
|
-
|
371
|
+
def get(paths = ['/'], options = {}, &block)
|
372
|
+
route('GET', paths, options, &block)
|
373
|
+
end
|
374
|
+
|
375
|
+
def post(paths = ['/'], options = {}, &block)
|
376
|
+
route('POST', paths, options, &block)
|
377
|
+
end
|
378
|
+
|
379
|
+
def put(paths = ['/'], options = {}, &block)
|
380
|
+
route('PUT', paths, options, &block)
|
381
|
+
end
|
382
|
+
|
383
|
+
def head(paths = ['/'], options = {}, &block)
|
384
|
+
route('HEAD', paths, options, &block)
|
385
|
+
end
|
386
|
+
|
387
|
+
def delete(paths = ['/'], options = {}, &block)
|
388
|
+
route('DELETE', paths, options, &block)
|
389
|
+
end
|
390
|
+
|
391
|
+
def options(paths = ['/'], options = {}, &block)
|
392
|
+
route('OPTIONS', paths, options, &block)
|
393
|
+
end
|
394
|
+
|
395
|
+
def patch(paths = ['/'], options = {}, &block)
|
396
|
+
route('PATCH', paths, options, &block)
|
397
|
+
end
|
371
398
|
|
372
399
|
def namespace(space = nil, options = {}, &block)
|
373
400
|
if space || block_given?
|
@@ -422,7 +449,10 @@ module Grape
|
|
422
449
|
# and arguments that are currently applied to the
|
423
450
|
# application.
|
424
451
|
def middleware
|
425
|
-
settings.stack.inject([])
|
452
|
+
settings.stack.inject([]) do |a, s|
|
453
|
+
a += s[:middleware] if s[:middleware]
|
454
|
+
a
|
455
|
+
end
|
426
456
|
end
|
427
457
|
|
428
458
|
# An array of API routes.
|
@@ -435,9 +465,11 @@ module Grape
|
|
435
465
|
end
|
436
466
|
|
437
467
|
def cascade(value = nil)
|
438
|
-
value.nil?
|
439
|
-
|
468
|
+
if value.nil?
|
469
|
+
settings.has_key?(:cascade) ? !!settings[:cascade] : true
|
470
|
+
else
|
440
471
|
set(:cascade, value)
|
472
|
+
end
|
441
473
|
end
|
442
474
|
|
443
475
|
protected
|
@@ -454,15 +486,15 @@ module Grape
|
|
454
486
|
# block passed in. Allows for simple 'before' setups
|
455
487
|
# of settings stack pushes.
|
456
488
|
def nest(*blocks, &block)
|
457
|
-
blocks.reject!{|b| b.nil?}
|
489
|
+
blocks.reject! { |b| b.nil? }
|
458
490
|
if blocks.any?
|
459
491
|
settings.push # create a new context to eval the follow
|
460
|
-
instance_eval
|
461
|
-
blocks.each{|b| instance_eval
|
462
|
-
settings.pop
|
492
|
+
instance_eval(&block) if block_given?
|
493
|
+
blocks.each { |b| instance_eval(&b) }
|
494
|
+
settings.pop # when finished, we pop the context
|
463
495
|
reset_validations!
|
464
496
|
else
|
465
|
-
instance_eval
|
497
|
+
instance_eval(&block)
|
466
498
|
end
|
467
499
|
end
|
468
500
|
|
@@ -492,7 +524,7 @@ module Grape
|
|
492
524
|
def call(env)
|
493
525
|
status, headers, body = @route_set.call(env)
|
494
526
|
headers.delete('X-Cascade') unless cascade?
|
495
|
-
[
|
527
|
+
[status, headers, body]
|
496
528
|
end
|
497
529
|
|
498
530
|
# Some requests may return a HTTP 404 error if grape cannot find a matching
|
@@ -504,8 +536,8 @@ module Grape
|
|
504
536
|
# errors from reaching upstream. This is effectivelly done by unsetting
|
505
537
|
# X-Cascade. Default :cascade is true.
|
506
538
|
def cascade?
|
507
|
-
return !!
|
508
|
-
return !!
|
539
|
+
return !!self.class.settings[:cascade] if self.class.settings.has_key?(:cascade)
|
540
|
+
return !!self.class.settings[:version_options][:cascade] if self.class.settings[:version_options] && self.class.settings[:version_options].has_key?(:cascade)
|
509
541
|
true
|
510
542
|
end
|
511
543
|
|
@@ -518,32 +550,34 @@ module Grape
|
|
518
550
|
# will return an HTTP 405 response for any HTTP method that the resource
|
519
551
|
# cannot handle.
|
520
552
|
def add_head_not_allowed_methods
|
521
|
-
allowed_methods = Hash.new{|h,k| h[k] = [] }
|
522
|
-
resources
|
523
|
-
endpoint.options[:app] && endpoint.options[:app].respond_to?(:endpoints)
|
524
|
-
endpoint.options[:app].endpoints.map(&:routes)
|
553
|
+
allowed_methods = Hash.new { |h, k| h[k] = [] }
|
554
|
+
resources = self.class.endpoints.map do |endpoint|
|
555
|
+
if endpoint.options[:app] && endpoint.options[:app].respond_to?(:endpoints)
|
556
|
+
endpoint.options[:app].endpoints.map(&:routes)
|
557
|
+
else
|
525
558
|
endpoint.routes
|
559
|
+
end
|
526
560
|
end
|
527
561
|
resources.flatten.each do |route|
|
528
562
|
allowed_methods[route.route_compiled] << route.route_method
|
529
563
|
end
|
530
564
|
allowed_methods.each do |path_info, methods|
|
531
|
-
if methods.include?('GET') && !
|
532
|
-
methods = methods | [
|
565
|
+
if methods.include?('GET') && !methods.include?("HEAD") && !self.class.settings[:do_not_route_head]
|
566
|
+
methods = methods | ['HEAD']
|
533
567
|
end
|
534
568
|
allow_header = (["OPTIONS"] | methods).join(", ")
|
535
569
|
unless methods.include?("OPTIONS") || self.class.settings[:do_not_route_options]
|
536
|
-
@route_set.add_route(
|
537
|
-
:
|
538
|
-
:
|
570
|
+
@route_set.add_route(proc { [204, { 'Allow' => allow_header }, []] }, {
|
571
|
+
path_info: path_info,
|
572
|
+
request_method: "OPTIONS"
|
539
573
|
})
|
540
574
|
end
|
541
575
|
not_allowed_methods = %w(GET PUT POST DELETE PATCH HEAD) - methods
|
542
576
|
not_allowed_methods << "OPTIONS" if self.class.settings[:do_not_route_options]
|
543
577
|
not_allowed_methods.each do |bad_method|
|
544
|
-
@route_set.add_route(
|
545
|
-
:
|
546
|
-
:
|
578
|
+
@route_set.add_route(proc { [405, { 'Allow' => allow_header, 'Content-Type' => 'text/plain' }, []] }, {
|
579
|
+
path_info: path_info,
|
580
|
+
request_method: bad_method
|
547
581
|
})
|
548
582
|
end
|
549
583
|
end
|