grape 1.3.2 → 1.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +82 -2
  3. data/LICENSE +1 -1
  4. data/README.md +120 -24
  5. data/UPGRADING.md +220 -39
  6. data/lib/grape.rb +3 -2
  7. data/lib/grape/api.rb +3 -3
  8. data/lib/grape/api/instance.rb +22 -25
  9. data/lib/grape/dsl/callbacks.rb +1 -1
  10. data/lib/grape/dsl/helpers.rb +1 -0
  11. data/lib/grape/dsl/inside_route.rb +70 -37
  12. data/lib/grape/dsl/parameters.rb +8 -4
  13. data/lib/grape/dsl/routing.rb +6 -7
  14. data/lib/grape/dsl/validations.rb +18 -1
  15. data/lib/grape/eager_load.rb +1 -1
  16. data/lib/grape/endpoint.rb +8 -6
  17. data/lib/grape/exceptions/validation.rb +1 -1
  18. data/lib/grape/exceptions/validation_errors.rb +1 -1
  19. data/lib/grape/middleware/auth/base.rb +3 -3
  20. data/lib/grape/middleware/base.rb +3 -2
  21. data/lib/grape/middleware/error.rb +11 -13
  22. data/lib/grape/middleware/formatter.rb +3 -3
  23. data/lib/grape/middleware/stack.rb +8 -1
  24. data/lib/grape/request.rb +1 -1
  25. data/lib/grape/router.rb +25 -39
  26. data/lib/grape/router/attribute_translator.rb +26 -5
  27. data/lib/grape/router/route.rb +1 -19
  28. data/lib/grape/{serve_file → serve_stream}/file_body.rb +1 -1
  29. data/lib/grape/{serve_file → serve_stream}/sendfile_response.rb +1 -1
  30. data/lib/grape/{serve_file/file_response.rb → serve_stream/stream_response.rb} +8 -8
  31. data/lib/grape/util/base_inheritable.rb +2 -2
  32. data/lib/grape/util/lazy_value.rb +1 -0
  33. data/lib/grape/validations/attributes_iterator.rb +8 -0
  34. data/lib/grape/validations/multiple_attributes_iterator.rb +1 -1
  35. data/lib/grape/validations/params_scope.rb +9 -7
  36. data/lib/grape/validations/single_attribute_iterator.rb +1 -1
  37. data/lib/grape/validations/types.rb +1 -4
  38. data/lib/grape/validations/types/array_coercer.rb +14 -5
  39. data/lib/grape/validations/types/build_coercer.rb +1 -5
  40. data/lib/grape/validations/types/custom_type_coercer.rb +15 -1
  41. data/lib/grape/validations/types/dry_type_coercer.rb +36 -1
  42. data/lib/grape/validations/types/invalid_value.rb +24 -0
  43. data/lib/grape/validations/types/primitive_coercer.rb +9 -3
  44. data/lib/grape/validations/types/set_coercer.rb +6 -4
  45. data/lib/grape/validations/types/variant_collection_coercer.rb +1 -1
  46. data/lib/grape/validations/validator_factory.rb +1 -1
  47. data/lib/grape/validations/validators/as.rb +1 -1
  48. data/lib/grape/validations/validators/base.rb +8 -8
  49. data/lib/grape/validations/validators/coerce.rb +8 -14
  50. data/lib/grape/validations/validators/default.rb +3 -5
  51. data/lib/grape/validations/validators/except_values.rb +1 -1
  52. data/lib/grape/validations/validators/multiple_params_base.rb +2 -1
  53. data/lib/grape/validations/validators/values.rb +1 -1
  54. data/lib/grape/version.rb +1 -1
  55. data/spec/grape/api/instance_spec.rb +50 -0
  56. data/spec/grape/api_remount_spec.rb +9 -4
  57. data/spec/grape/api_spec.rb +75 -0
  58. data/spec/grape/dsl/inside_route_spec.rb +182 -33
  59. data/spec/grape/endpoint/declared_spec.rb +601 -0
  60. data/spec/grape/endpoint_spec.rb +0 -521
  61. data/spec/grape/entity_spec.rb +7 -1
  62. data/spec/grape/integration/rack_sendfile_spec.rb +12 -8
  63. data/spec/grape/middleware/auth/strategies_spec.rb +1 -1
  64. data/spec/grape/middleware/error_spec.rb +1 -1
  65. data/spec/grape/middleware/formatter_spec.rb +1 -1
  66. data/spec/grape/middleware/stack_spec.rb +1 -0
  67. data/spec/grape/request_spec.rb +1 -1
  68. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +13 -3
  69. data/spec/grape/validations/params_scope_spec.rb +26 -0
  70. data/spec/grape/validations/single_attribute_iterator_spec.rb +17 -6
  71. data/spec/grape/validations/types/array_coercer_spec.rb +35 -0
  72. data/spec/grape/validations/types/primitive_coercer_spec.rb +65 -5
  73. data/spec/grape/validations/types/set_coercer_spec.rb +34 -0
  74. data/spec/grape/validations/validators/coerce_spec.rb +223 -25
  75. data/spec/grape/validations/validators/default_spec.rb +170 -0
  76. data/spec/grape/validations/validators/except_values_spec.rb +1 -0
  77. data/spec/grape/validations/validators/values_spec.rb +1 -1
  78. data/spec/grape/validations_spec.rb +290 -18
  79. data/spec/integration/eager_load/eager_load_spec.rb +15 -0
  80. data/spec/shared/versioning_examples.rb +20 -20
  81. data/spec/spec_helper.rb +0 -10
  82. data/spec/support/chunks.rb +14 -0
  83. data/spec/support/versioned_helpers.rb +4 -6
  84. metadata +20 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a1ba205b72fd823b11e700753891784fdfbd6791f591b790a99ac3433cb8fe23
4
- data.tar.gz: '09e64a0d93415b28fdb179fbb5d7ef0d03e00dcb976fd885c0c655d6ac041345'
3
+ metadata.gz: ac9fdc749f4dcad72fa8baacf0b07fa0fa499552521c789dd8e84439554ce275
4
+ data.tar.gz: 075b2bc7e75e7b0240973086cdae37cd2adf10ef4a4c419dc2cccd7a2741a3cd
5
5
  SHA512:
6
- metadata.gz: 06fcd2157bcfcc6e71876df09b34a318c600761b79fb99ad77739521d056950ee8391dfd050efd43618f7f99f11990623e276b32d15a27e92015ec3a56c6c08b
7
- data.tar.gz: 5463bbd0347950765c9d92e859965e90dd69d7d1f781fd188386cf39597c196f5ba2dc697dbee4f896a70f6498c1e43034a33db8460ea9a719218a7d5df46d6f
6
+ metadata.gz: b845801e8c95ceee643853fd306c1513ce0611ebd535f3e2f058e95b4c491da08f58bcbd33b8d42d2cd8f1432d619dda203f8243fcc72e2b808ec4d0e15bc81c
7
+ data.tar.gz: ccdf098f65e4331fc35eaab564fbaf8d7411d1ae6f394f4cf4e0fdfa4f4871092e60b23a8a3a60ffc95680e3287446cac343932b0ef2af6b0745b91422d1d0a4
data/CHANGELOG.md CHANGED
@@ -1,6 +1,85 @@
1
+ ### 1.5.2 (2021/02/06)
2
+
3
+ #### Features
4
+
5
+ * [#2157](https://github.com/ruby-grape/grape/pull/2157): Custom types can set a message to be used in the response when invalid - [@dnesteryuk](https://github.com/dnesteryuk).
6
+ * [#2145](https://github.com/ruby-grape/grape/pull/2145): Ruby 3.0 compatibility - [@ericproulx](https://github.com/ericproulx).
7
+ * [#2143](https://github.com/ruby-grape/grape/pull/2143): Enable GitHub Actions with updated RuboCop and Danger - [@anakinj](https://github.com/anakinj).
8
+
9
+ #### Fixes
10
+
11
+ * [#2144](https://github.com/ruby-grape/grape/pull/2144): Fix compatibility issue with activesupport 6.1 and XML serialization of arrays - [@anakinj](https://github.com/anakinj).
12
+ * [#2137](https://github.com/ruby-grape/grape/pull/2137): Fix typos - [@johnny-miyake](https://github.com/johnny-miyake).
13
+ * [#2131](https://github.com/ruby-grape/grape/pull/2131): Fix Ruby 2.7 keyword deprecation warning in validators/coerce - [@K0H205](https://github.com/K0H205).
14
+ * [#2132](https://github.com/ruby-grape/grape/pull/2132): Use #ruby2_keywords for correct delegation on Ruby <= 2.6, 2.7 and 3 - [@eregon](https://github.com/eregon).
15
+ * [#2152](https://github.com/ruby-grape/grape/pull/2152): Fix configuration method inside namespaced params - [@fsainz](https://github.com/fsainz).
16
+
17
+ ### 1.5.1 (2020/11/15)
18
+
19
+ #### Fixes
20
+
21
+ * [#2129](https://github.com/ruby-grape/grape/pull/2129): Fix validation error when Required Array nested inside an optional array, for Multiparam validators - [@dwhenry](https://github.com/dwhenry).
22
+ * [#2128](https://github.com/ruby-grape/grape/pull/2128): Fix validation error when Required Array nested inside an optional array - [@dwhenry](https://github.com/dwhenry).
23
+ * [#2127](https://github.com/ruby-grape/grape/pull/2127): Fix a performance issue with dependent params - [@dnesteryuk](https://github.com/dnesteryuk).
24
+ * [#2126](https://github.com/ruby-grape/grape/pull/2126): Fix warnings about redefined attribute accessors in `AttributeTranslator` - [@samsonjs](https://github.com/samsonjs).
25
+ * [#2121](https://github.com/ruby-grape/grape/pull/2121): Fix 2.7 deprecation warning in validator_factory - [@Legogris](https://github.com/Legogris).
26
+ * [#2115](https://github.com/ruby-grape/grape/pull/2115): Fix declared_params regression with multiple allowed types - [@stanhu](https://github.com/stanhu).
27
+ * [#2123](https://github.com/ruby-grape/grape/pull/2123): Fix 2.7 deprecation warning in middleware/stack - [@Legogris](https://github.com/Legogris).
28
+
29
+ ### 1.5.0 (2020/10/05)
30
+
31
+ #### Fixes
32
+
33
+ * [#2104](https://github.com/ruby-grape/grape/pull/2104): Fix Ruby 2.7 keyword deprecation warning - [@stanhu](https://github.com/stanhu).
34
+ * [#2103](https://github.com/ruby-grape/grape/pull/2103): Ensure complete declared params structure is present - [@tlconnor](https://github.com/tlconnor).
35
+ * [#2099](https://github.com/ruby-grape/grape/pull/2099): Added truffleruby to Travis-CI - [@gogainda](https://github.com/gogainda).
36
+ * [#2089](https://github.com/ruby-grape/grape/pull/2089): Specify order of mounting Grape with Rack::Cascade in README - [@jonmchan](https://github.com/jonmchan).
37
+ * [#2088](https://github.com/ruby-grape/grape/pull/2088): Set `Cache-Control` header only for streamed responses - [@stanhu](https://github.com/stanhu).
38
+ * [#2092](https://github.com/ruby-grape/grape/pull/2092): Correct an example params in Include Missing doc - [@huyvohcmc](https://github.com/huyvohcmc).
39
+ * [#2091](https://github.com/ruby-grape/grape/pull/2091): Fix ruby 2.7 keyword deprecations - [@dim](https://github.com/dim).
40
+ * [#2097](https://github.com/ruby-grape/grape/pull/2097): Skip to set default value unless `meets_dependency?` - [@wanabe](https://github.com/wanabe).
41
+ * [#2096](https://github.com/ruby-grape/grape/pull/2096): Fix redundant dependency check - [@braktar](https://github.com/braktar).
42
+ * [#2096](https://github.com/ruby-grape/grape/pull/2098): Fix nested coercion - [@braktar](https://github.com/braktar).
43
+ * [#2102](https://github.com/ruby-grape/grape/pull/2102): Fix retaining setup blocks when remounting APIs - [@jylamont](https://github.com/jylamont).
44
+
45
+ ### 1.4.0 (2020/07/10)
46
+
47
+ #### Features
48
+
49
+ * [#1520](https://github.com/ruby-grape/grape/pull/1520): Un-deprecate stream-like objects - [@urkle](https://github.com/urkle).
50
+ * [#2060](https://github.com/ruby-grape/grape/pull/2060): Drop support for Ruby 2.4 - [@dblock](https://github.com/dblock).
51
+ * [#2060](https://github.com/ruby-grape/grape/pull/2060): Upgraded Rubocop to 0.84.0 - [@dblock](https://github.com/dblock).
52
+ * [#2077](https://github.com/ruby-grape/grape/pull/2077): Simplify logic for defining declared params - [@dnesteryuk](https://github.com/dnesteryuk).
53
+ * [#2076](https://github.com/ruby-grape/grape/pull/2076): Make route information available for hooks when the automatically generated endpoints are invoked - [@anakinj](https://github.com/anakinj).
54
+
55
+ #### Fixes
56
+
57
+ * [#2067](https://github.com/ruby-grape/grape/pull/2067): Coerce empty String to `nil` for all primitive types except `String` - [@petekinnecom](https://github.com/petekinnecom).
58
+ * [#2064](https://github.com/ruby-grape/grape/pull/2064): Fix Ruby 2.7 deprecation warning in `Grape::Middleware::Base#initialize` - [@skarger](https://github.com/skarger).
59
+ * [#2072](https://github.com/ruby-grape/grape/pull/2072): Fix `Grape.eager_load!` and `compile!` - [@stanhu](https://github.com/stanhu).
60
+ * [#2084](https://github.com/ruby-grape/grape/pull/2084): Fix memory leak in path normalization - [@fcheung](https://github.com/fcheung).
61
+
62
+ ### 1.3.3 (2020/05/23)
63
+
64
+ #### Features
65
+
66
+ * [#2048](https://github.com/ruby-grape/grape/issues/2034): Grape Enterprise support is now available [via TideLift](https://tidelift.com/subscription/request-a-demo?utm_source=rubygems-grape&utm_medium=referral&utm_campaign=enterprise) - [@dblock](https://github.com/dblock).
67
+ * [#2039](https://github.com/ruby-grape/grape/pull/2039): Travis - update rails versions - [@ericproulx](https://github.com/ericproulx).
68
+ * [#2038](https://github.com/ruby-grape/grape/pull/2038): Travis - update ruby versions - [@ericproulx](https://github.com/ericproulx).
69
+ * [#2050](https://github.com/ruby-grape/grape/pull/2050): Refactor route public_send to AttributeTranslator - [@ericproulx](https://github.com/ericproulx).
70
+
71
+ #### Fixes
72
+
73
+ * [#2049](https://github.com/ruby-grape/grape/pull/2049): Coerce an empty string to nil in case of the bool type - [@dnesteryuk](https://github.com/dnesteryuk).
74
+ * [#2043](https://github.com/ruby-grape/grape/pull/2043): Modify declared for nested array and hash - [@kadotami](https://github.com/kadotami).
75
+ * [#2040](https://github.com/ruby-grape/grape/pull/2040): Fix a regression with Array of type nil - [@ericproulx](https://github.com/ericproulx).
76
+ * [#2054](https://github.com/ruby-grape/grape/pull/2054): Coercing of nested arrays - [@dnesteryuk](https://github.com/dnesteryuk).
77
+ * [#2050](https://github.com/ruby-grape/grape/pull/2053): Fix broken multiple mounts - [@Jack12816](https://github.com/Jack12816).
78
+
1
79
  ### 1.3.2 (2020/04/12)
2
80
 
3
81
  #### Features
82
+
4
83
  * [#2020](https://github.com/ruby-grape/grape/pull/2020): Reduce array allocation - [@ericproulx](https://github.com/ericproulx).
5
84
  * [#2015](https://github.com/ruby-grape/grape/pull/2014): Reduce MatchData allocation - [@ericproulx](https://github.com/ericproulx).
6
85
  * [#2014](https://github.com/ruby-grape/grape/pull/2014): Reduce total allocated arrays - [@ericproulx](https://github.com/ericproulx).
@@ -34,7 +113,8 @@
34
113
  * [#1976](https://github.com/ruby-grape/grape/pull/1976): Ensure classes/modules listed for autoload really exist - [@dnesteryuk](https://github.com/dnesteryuk).
35
114
  * [#1971](https://github.com/ruby-grape/grape/pull/1971): Fix BigDecimal coercion - [@FlickStuart](https://github.com/FlickStuart).
36
115
  * [#1968](https://github.com/ruby-grape/grape/pull/1968): Fix args forwarding in Grape::Middleware::Stack#merge_with for ruby 2.7.0 - [@dm1try](https://github.com/dm1try).
37
- * [#1988](https://github.com/ruby-grape/grape/pull/1988): Refactored the full_messages method and stop overriding full_message - [@hosseintoussi](https://github.com/hosseintoussi).
116
+ * [#1988](https://github.com/ruby-grape/grape/pull/1988): Refactor the full_messages method and stop overriding full_message - [@hosseintoussi](https://github.com/hosseintoussi).
117
+ * [#1956](https://github.com/ruby-grape/grape/pull/1956): Comply with Rack spec, fix `undefined method [] for nil:NilClass` error when upgrading Rack - [@ioquatix](https://github.com/ioquatix).
38
118
 
39
119
  ### 1.3.0 (2020/01/11)
40
120
 
@@ -557,7 +637,7 @@
557
637
  * [#492](https://github.com/ruby-grape/grape/pull/492): Don't allow to have nil value when a param is required and has a list of allowed values - [@Antti](https://github.com/Antti).
558
638
  * [#495](https://github.com/ruby-grape/grape/pull/495): Fixed `ParamsScope#params` for parameters nested inside arrays - [@asross](https://github.com/asross).
559
639
  * [#498](https://github.com/ruby-grape/grape/pull/498): Dry'ed up options and headers logic, allow headers to be passed to OPTIONS requests - [@karlfreeman](https://github.com/karlfreeman).
560
- * [#500](https://github.com/ruby-grape/grape/pull/500): Skip entity auto-detection when explicitely passed - [@yaneq](https://github.com/yaneq).
640
+ * [#500](https://github.com/ruby-grape/grape/pull/500): Skip entity auto-detection when explicitly passed - [@yaneq](https://github.com/yaneq).
561
641
  * [#503](https://github.com/ruby-grape/grape/pull/503): Calling declared(params) from child namespace fails to include parent namespace defined params - [@myitcv](https://github.com/myitcv).
562
642
  * [#512](https://github.com/ruby-grape/grape/pull/512): Don't create `Grape::Request` multiple times - [@dblock](https://github.com/dblock).
563
643
  * [#538](https://github.com/ruby-grape/grape/pull/538): Fixed default values for grouped params - [@dm1try](https://github.com/dm1try).
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010-2019 Michael Bleigh, Intridea Inc. and Contributors.
1
+ Copyright (c) 2010-2020 Michael Bleigh, Intridea Inc. and Contributors.
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  ![grape logo](grape.png)
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/grape.svg)](http://badge.fury.io/rb/grape)
4
- [![Build Status](https://travis-ci.org/ruby-grape/grape.svg?branch=master)](https://travis-ci.org/ruby-grape/grape)
4
+ [![Build Status](https://github.com/ruby-grape/grape/workflows/test/badge.svg?branch=master)](https://github.com/ruby-grape/grape/actions)
5
5
  [![Code Climate](https://codeclimate.com/github/ruby-grape/grape.svg)](https://codeclimate.com/github/ruby-grape/grape)
6
6
  [![Coverage Status](https://coveralls.io/repos/github/ruby-grape/grape/badge.svg?branch=master)](https://coveralls.io/github/ruby-grape/grape?branch=master)
7
7
  [![Inline docs](https://inch-ci.org/github/ruby-grape/grape.svg)](https://inch-ci.org/github/ruby-grape/grape)
@@ -12,12 +12,15 @@
12
12
  - [What is Grape?](#what-is-grape)
13
13
  - [Stable Release](#stable-release)
14
14
  - [Project Resources](#project-resources)
15
+ - [Grape for Enterprise](#grape-for-enterprise)
15
16
  - [Installation](#installation)
16
17
  - [Basic Usage](#basic-usage)
17
18
  - [Mounting](#mounting)
18
19
  - [All](#all)
19
20
  - [Rack](#rack)
20
21
  - [ActiveRecord without Rails](#activerecord-without-rails)
22
+ - [Rails 4](#rails-4)
23
+ - [Rails 5+](#rails-5)
21
24
  - [Alongside Sinatra (or other frameworks)](#alongside-sinatra-or-other-frameworks)
22
25
  - [Rails](#rails)
23
26
  - [Rails < 5.2](#rails--52)
@@ -141,6 +144,7 @@
141
144
  - [format_response.grape](#format_responsegrape)
142
145
  - [Monitoring Products](#monitoring-products)
143
146
  - [Contributing to Grape](#contributing-to-grape)
147
+ - [Security](#security)
144
148
  - [License](#license)
145
149
  - [Copyright](#copyright)
146
150
 
@@ -154,7 +158,7 @@ content negotiation, versioning and much more.
154
158
 
155
159
  ## Stable Release
156
160
 
157
- You're reading the documentation for the stable release of Grape, 1.3.2.
161
+ You're reading the documentation for the stable release of Grape, 1.5.2.
158
162
 
159
163
  ## Project Resources
160
164
 
@@ -163,6 +167,14 @@ You're reading the documentation for the stable release of Grape, 1.3.2.
163
167
  * Need help? Try [Grape Google Group](http://groups.google.com/group/ruby-grape) or [Gitter](https://gitter.im/ruby-grape/grape)
164
168
  * [Follow us on Twitter](https://twitter.com/grapeframework)
165
169
 
170
+ ## Grape for Enterprise
171
+
172
+ Available as part of the Tidelift Subscription.
173
+
174
+ The maintainers of Grape are working with Tidelift to deliver commercial support and maintenance. Save time, reduce risk, and improve code health, while paying the maintainers of Grape. Click [here](https://tidelift.com/subscription/request-a-demo?utm_source=rubygems-grape&utm_medium=referral&utm_campaign=enterprise) for more details.
175
+
176
+ In 2020, we plan to use the money towards gathering Grape contributors for dinner in New York City.
177
+
166
178
  ## Installation
167
179
 
168
180
  Ruby 2.4 or newer is required.
@@ -305,13 +317,21 @@ Grape will also automatically respond to HEAD and OPTIONS for all GET, and just
305
317
  If you want to use ActiveRecord within Grape, you will need to make sure that ActiveRecord's connection pool
306
318
  is handled correctly.
307
319
 
320
+ #### Rails 4
321
+
308
322
  The easiest way to achieve that is by using ActiveRecord's `ConnectionManagement` middleware in your
309
323
  `config.ru` before mounting Grape, e.g.:
310
324
 
311
325
  ```ruby
312
326
  use ActiveRecord::ConnectionAdapters::ConnectionManagement
327
+ ```
313
328
 
314
- run Twitter::API
329
+ #### Rails 5+
330
+
331
+ Use [otr-activerecord](https://github.com/jhollinger/otr-activerecord) as follows:
332
+
333
+ ```ruby
334
+ use OTR::ActiveRecord::ConnectionManagement
315
335
  ```
316
336
 
317
337
  ### Alongside Sinatra (or other frameworks)
@@ -338,9 +358,12 @@ class Web < Sinatra::Base
338
358
  end
339
359
 
340
360
  use Rack::Session::Cookie
341
- run Rack::Cascade.new [API, Web]
361
+ run Rack::Cascade.new [Web, API]
342
362
  ```
343
363
 
364
+ Note that order of loading apps using `Rack::Cascade` matters. The grape application must be last if you want to raise custom 404 errors from grape (such as `error!('Not Found',404)`). If the grape application is not last and returns 404 or 405 response, [cascade utilizes that as a signal to try the next app](https://www.rubydoc.info/gems/rack/Rack/Cascade). This may lead to undesirable behavior showing the [wrong 404 page from the wrong app](https://github.com/ruby-grape/grape/issues/1515).
365
+
366
+
344
367
  ### Rails
345
368
 
346
369
  Place API files into `app/api`. Rails expects a subdirectory that matches the name of the Ruby module and a file name that matches the name of the class. In our example, the file name location and directory for `Twitter::API` should be `app/api/twitter/api.rb`.
@@ -772,7 +795,12 @@ Available parameter builders are `Grape::Extensions::Hash::ParamBuilder`, `Grape
772
795
 
773
796
  ### Declared
774
797
 
775
- Grape allows you to access only the parameters that have been declared by your `params` block. It filters out the params that have been passed, but are not allowed. Consider the following API endpoint:
798
+ Grape allows you to access only the parameters that have been declared by your `params` block. It will:
799
+
800
+ * Filter out the params that have been passed, but are not allowed.
801
+ * Include any optional params that are declared but not passed.
802
+
803
+ Consider the following API endpoint:
776
804
 
777
805
  ````ruby
778
806
  format :json
@@ -805,9 +833,9 @@ Once we add parameters requirements, grape will start returning only the declare
805
833
  format :json
806
834
 
807
835
  params do
808
- requires :user, type: Hash do
809
- requires :first_name, type: String
810
- requires :last_name, type: String
836
+ optional :user, type: Hash do
837
+ optional :first_name, type: String
838
+ optional :last_name, type: String
811
839
  end
812
840
  end
813
841
 
@@ -835,6 +863,44 @@ curl -X POST -H "Content-Type: application/json" localhost:9292/users/signup -d
835
863
  }
836
864
  ````
837
865
 
866
+ Missing params that are declared as type `Hash` or `Array` will be included.
867
+
868
+ ````ruby
869
+ format :json
870
+
871
+ params do
872
+ optional :user, type: Hash do
873
+ optional :first_name, type: String
874
+ optional :last_name, type: String
875
+ end
876
+ optional :widgets, type: Array
877
+ end
878
+
879
+ post 'users/signup' do
880
+ { 'declared_params' => declared(params) }
881
+ end
882
+ ````
883
+
884
+ **Request**
885
+
886
+ ````bash
887
+ curl -X POST -H "Content-Type: application/json" localhost:9292/users/signup -d '{}'
888
+ ````
889
+
890
+ **Response**
891
+
892
+ ````json
893
+ {
894
+ "declared_params": {
895
+ "user": {
896
+ "first_name": null,
897
+ "last_name": null
898
+ },
899
+ "widgets": []
900
+ }
901
+ }
902
+ ````
903
+
838
904
  The returned hash is an `ActiveSupport::HashWithIndifferentAccess`.
839
905
 
840
906
  The `#declared` method is not available to `before` filters, as those are evaluated prior to parameter coercion.
@@ -893,8 +959,10 @@ By default `declared(params)` includes parameters that have `nil` values. If you
893
959
  format :json
894
960
 
895
961
  params do
896
- requires :first_name, type: String
897
- optional :last_name, type: String
962
+ requires :user, type: Hash do
963
+ requires :first_name, type: String
964
+ optional :last_name, type: String
965
+ end
898
966
  end
899
967
 
900
968
  post 'users/signup' do
@@ -1047,13 +1115,13 @@ params do
1047
1115
  end
1048
1116
  ```
1049
1117
 
1050
- Note that default values will be passed through to any validation options specified.
1051
- The following example will always fail if `:color` is not explicitly provided.
1052
-
1053
1118
  Default values are eagerly evaluated. Above `:non_random_number` will evaluate to the same
1054
1119
  number for each call to the endpoint of this `params` block. To have the default evaluate
1055
1120
  lazily with each request use a lambda, like `:random_number` above.
1056
1121
 
1122
+ Note that default values will be passed through to any validation options specified.
1123
+ The following example will always fail if `:color` is not explicitly provided.
1124
+
1057
1125
  ```ruby
1058
1126
  params do
1059
1127
  optional :color, type: String, default: 'blue', values: ['red', 'green']
@@ -1113,7 +1181,8 @@ Aside from the default set of supported types listed above, any class can be
1113
1181
  used as a type as long as an explicit coercion method is supplied. If the type
1114
1182
  implements a class-level `parse` method, Grape will use it automatically.
1115
1183
  This method must take one string argument and return an instance of the correct
1116
- type, or raise an exception to indicate the value was invalid. E.g.,
1184
+ type, or return an instance of `Grape::Types::InvalidValue` which optionally
1185
+ accepts a message to be returned in the response.
1117
1186
 
1118
1187
  ```ruby
1119
1188
  class Color
@@ -1123,8 +1192,9 @@ class Color
1123
1192
  end
1124
1193
 
1125
1194
  def self.parse(value)
1126
- fail 'Invalid color' unless %w(blue red green).include?(value)
1127
- new(value)
1195
+ return new(value) if %w[blue red green]).include?(value)
1196
+
1197
+ Grape::Types::InvalidValue.new('Unsupported color')
1128
1198
  end
1129
1199
  end
1130
1200
 
@@ -1980,10 +2050,10 @@ end
1980
2050
 
1981
2051
  # is NOT the same as
1982
2052
 
1983
- get ':status' do # this makes param[:status] available
2053
+ get ':status' do # this makes params[:status] available
1984
2054
  end
1985
2055
 
1986
- # This will make both param[:status_id] and param[:id] available
2056
+ # This will make both params[:status_id] and params[:id] available
1987
2057
 
1988
2058
  get 'statuses/:status_id/reviews/:id' do
1989
2059
  end
@@ -3156,17 +3226,19 @@ end
3156
3226
 
3157
3227
  Use `body false` to return `204 No Content` without any data or content-type.
3158
3228
 
3159
- You can also set the response to a file with `file`.
3229
+ You can also set the response to a file with `sendfile`. This works with the
3230
+ [Rack::Sendfile](https://www.rubydoc.info/gems/rack/Rack/Sendfile) middleware to optimally send
3231
+ the file through your web server software.
3160
3232
 
3161
3233
  ```ruby
3162
3234
  class API < Grape::API
3163
3235
  get '/' do
3164
- file '/path/to/file'
3236
+ sendfile '/path/to/file'
3165
3237
  end
3166
3238
  end
3167
3239
  ```
3168
3240
 
3169
- If you want a file to be streamed using Rack::Chunked, use `stream`.
3241
+ To stream a file in chunks use `stream`
3170
3242
 
3171
3243
  ```ruby
3172
3244
  class API < Grape::API
@@ -3176,6 +3248,26 @@ class API < Grape::API
3176
3248
  end
3177
3249
  ```
3178
3250
 
3251
+ If you want to stream non-file data use the `stream` method and a `Stream` object.
3252
+ This is an object that responds to `each` and yields for each chunk to send to the client.
3253
+ Each chunk will be sent as it is yielded instead of waiting for all of the content to be available.
3254
+
3255
+ ```ruby
3256
+ class MyStream
3257
+ def each
3258
+ yield 'part 1'
3259
+ yield 'part 2'
3260
+ yield 'part 3'
3261
+ end
3262
+ end
3263
+
3264
+ class API < Grape::API
3265
+ get '/' do
3266
+ stream MyStream.new
3267
+ end
3268
+ end
3269
+ ```
3270
+
3179
3271
  ## Authentication
3180
3272
 
3181
3273
  ### Basic and Digest Auth
@@ -3850,7 +3942,7 @@ Grape integrates with following third-party tools:
3850
3942
  * **Librato Metrics** - [grape-librato](https://github.com/seanmoon/grape-librato) gem
3851
3943
  * **[Skylight](https://www.skylight.io/)** - [skylight](https://github.com/skylightio/skylight-ruby) gem, [documentation](https://docs.skylight.io/grape/)
3852
3944
  * **[AppSignal](https://www.appsignal.com)** - [appsignal-ruby](https://github.com/appsignal/appsignal-ruby) gem, [documentation](http://docs.appsignal.com/getting-started/supported-frameworks.html#grape)
3853
- * **[ElasticAPM](https://www.elastic.co/products/apm) - [elastic-apm](https://github.com/elastic/apm-agent-ruby) gem, [documentation](https://www.elastic.co/guide/en/apm/agent/ruby/3.x/getting-started-rack.html#getting-started-grape)
3945
+ * **[ElasticAPM](https://www.elastic.co/products/apm)** - [elastic-apm](https://github.com/elastic/apm-agent-ruby) gem, [documentation](https://www.elastic.co/guide/en/apm/agent/ruby/3.x/getting-started-rack.html#getting-started-grape)
3854
3946
 
3855
3947
  ## Contributing to Grape
3856
3948
 
@@ -3859,10 +3951,14 @@ features and discuss issues.
3859
3951
 
3860
3952
  See [CONTRIBUTING](CONTRIBUTING.md).
3861
3953
 
3954
+ ## Security
3955
+
3956
+ See [SECURITY](SECURITY.md) for details.
3957
+
3862
3958
  ## License
3863
3959
 
3864
- MIT License. See LICENSE for details.
3960
+ MIT License. See [LICENSE](LICENSE) for details.
3865
3961
 
3866
3962
  ## Copyright
3867
3963
 
3868
- Copyright (c) 2010-2019 Michael Bleigh, Intridea Inc. and Contributors.
3964
+ Copyright (c) 2010-2020 Michael Bleigh, Intridea Inc. and Contributors.
data/UPGRADING.md CHANGED
@@ -1,6 +1,192 @@
1
1
  Upgrading Grape
2
2
  ===============
3
3
 
4
+ ### Upgrading to >= 1.5.1
5
+
6
+ #### Dependent params
7
+
8
+ If you use [dependent params](https://github.com/ruby-grape/grape#dependent-parameters) with
9
+ `Grape::Extensions::Hash::ParamBuilder`, make sure a parameter to be dependent on is set as a Symbol.
10
+ If a String is given, a parameter that other parameters depend on won't be found even if it is present.
11
+
12
+ _Correct_:
13
+ ```ruby
14
+ given :matrix do
15
+ # dependent params
16
+ end
17
+ ```
18
+
19
+ _Wrong_:
20
+ ```ruby
21
+ given 'matrix' do
22
+ # dependent params
23
+ end
24
+ ```
25
+
26
+ ### Upgrading to >= 1.5.0
27
+
28
+ Prior to 1.3.3, the `declared` helper would always return the complete params structure if `include_missing=true` was set. In 1.3.3 a regression was introduced such that a missing Hash with or without nested parameters would always resolve to `{}`.
29
+
30
+ In 1.5.0 this behavior is reverted, so the whole params structure will always be available via `declared`, regardless of whether any params are passed.
31
+
32
+ The following rules now apply to the `declared` helper when params are missing and `include_missing=true`:
33
+
34
+ * Hash params with children will resolve to a Hash with keys for each declared child.
35
+ * Hash params with no children will resolve to `{}`.
36
+ * Set params will resolve to `Set.new`.
37
+ * Array params will resolve to `[]`.
38
+ * All other params will resolve to `nil`.
39
+
40
+ #### Example
41
+
42
+ ```ruby
43
+ class Api < Grape::API
44
+ params do
45
+ optional :outer, type: Hash do
46
+ optional :inner, type: Hash do
47
+ optional :value, type: String
48
+ end
49
+ end
50
+ end
51
+ get 'example' do
52
+ declared(params, include_missing: true)
53
+ end
54
+ end
55
+ ```
56
+
57
+ ```
58
+ get '/example'
59
+ # 1.3.3 = {}
60
+ # 1.5.0 = {outer: {inner: {value:null}}}
61
+ ```
62
+
63
+ For more information see [#2103](https://github.com/ruby-grape/grape/pull/2103).
64
+
65
+ ### Upgrading to >= 1.4.0
66
+
67
+ #### Reworking stream and file and un-deprecating stream like-objects
68
+
69
+ Previously in 0.16 stream-like objects were deprecated. This release restores their functionality for use-cases other than file streaming.
70
+
71
+ This release deprecated `file` in favor of `sendfile` to better document its purpose.
72
+
73
+ To deliver a file via the Sendfile support in your web server and have the Rack::Sendfile middleware enabled. See [`Rack::Sendfile`](https://www.rubydoc.info/gems/rack/Rack/Sendfile).
74
+ ```ruby
75
+ class API < Grape::API
76
+ get '/' do
77
+ sendfile '/path/to/file'
78
+ end
79
+ end
80
+ ```
81
+
82
+ Use `stream` to stream file content in chunks.
83
+
84
+ ```ruby
85
+ class API < Grape::API
86
+ get '/' do
87
+ stream '/path/to/file'
88
+ end
89
+ end
90
+ ```
91
+
92
+ Or use `stream` to stream other kinds of content. In the following example a streamer class
93
+ streams paginated data from a database.
94
+
95
+ ```ruby
96
+ class MyObject
97
+ attr_accessor :result
98
+
99
+ def initialize(query)
100
+ @result = query
101
+ end
102
+
103
+ def each
104
+ yield '['
105
+ # Do paginated DB fetches and return each page formatted
106
+ first = false
107
+ result.find_in_batches do |records|
108
+ yield process_records(records, first)
109
+ first = false
110
+ end
111
+ yield ']'
112
+ end
113
+
114
+ def process_records(records, first)
115
+ buffer = +''
116
+ buffer << ',' unless first
117
+ buffer << records.map(&:to_json).join(',')
118
+ buffer
119
+ end
120
+ end
121
+
122
+ class API < Grape::API
123
+ get '/' do
124
+ stream MyObject.new(Sprocket.all)
125
+ end
126
+ end
127
+ ```
128
+
129
+ ### Upgrading to >= 1.3.3
130
+
131
+ #### Nil values for structures
132
+
133
+ Nil values always been a special case when dealing with types especially with the following structures:
134
+
135
+ - Array
136
+ - Hash
137
+ - Set
138
+
139
+ The behavior for these structures has change through out the latest releases. For example:
140
+
141
+ ```ruby
142
+ class Api < Grape::API
143
+ params do
144
+ require :my_param, type: Array[Integer]
145
+ end
146
+
147
+ get 'example' do
148
+ params[:my_param]
149
+ end
150
+ get '/example', params: { my_param: nil }
151
+ # 1.3.1 = []
152
+ # 1.3.2 = nil
153
+ end
154
+ ```
155
+
156
+ For now on, `nil` values stay `nil` values for all types, including arrays, sets and hashes.
157
+
158
+ If you want to have the same behavior as 1.3.1, apply a `default` validator:
159
+
160
+ ```ruby
161
+ class Api < Grape::API
162
+ params do
163
+ require :my_param, type: Array[Integer], default: []
164
+ end
165
+
166
+ get 'example' do
167
+ params[:my_param]
168
+ end
169
+ get '/example', params: { my_param: nil } # => []
170
+ end
171
+ ```
172
+
173
+ #### Default validator
174
+
175
+ Default validator is now applied for `nil` values.
176
+
177
+ ```ruby
178
+ class Api < Grape::API
179
+ params do
180
+ requires :my_param, type: Integer, default: 0
181
+ end
182
+
183
+ get 'example' do
184
+ params[:my_param]
185
+ end
186
+ get '/example', params: { my_param: nil } #=> before: nil, after: 0
187
+ end
188
+ ```
189
+
4
190
  ### Upgrading to >= 1.3.0
5
191
 
6
192
  #### Ruby
@@ -9,10 +195,7 @@ After adding dry-types, Ruby 2.4 or newer is required.
9
195
 
10
196
  #### Coercion
11
197
 
12
- [Virtus](https://github.com/solnic/virtus) has been replaced by
13
- [dry-types](https://dry-rb.org/gems/dry-types/1.2/) for parameter
14
- coercion. If your project depends on Virtus outside of Grape, explicitly
15
- add it to your `Gemfile`.
198
+ [Virtus](https://github.com/solnic/virtus) has been replaced by [dry-types](https://dry-rb.org/gems/dry-types/1.2/) for parameter coercion. If your project depends on Virtus outside of Grape, explicitly add it to your `Gemfile`.
16
199
 
17
200
  Here's an example of how to migrate a custom type from Virtus to dry-types:
18
201
 
@@ -39,10 +222,7 @@ To use dry-types, we need to:
39
222
  1. Rename `coerce` to `self.parse`
40
223
  1. Rename `value_coerced?` to `self.parsed?`
41
224
 
42
- The custom type must have a class-level `parse` method to the model. A
43
- class-level `parsed?` is needed if the parsed type differs from the
44
- defined type. In the example below, since `SecureUri` is not the same
45
- as `URI::HTTPS`, `self.parsed?` is needed:
225
+ The custom type must have a class-level `parse` method to the model. A class-level `parsed?` is needed if the parsed type differs from the defined type. In the example below, since `SecureUri` is not the same as `URI::HTTPS`, `self.parsed?` is needed:
46
226
 
47
227
  ```ruby
48
228
  # New dry-types parser
@@ -61,21 +241,31 @@ params do
61
241
  end
62
242
  ```
63
243
 
244
+ #### Coercing to `FalseClass` or `TrueClass` no longer works
245
+
246
+ Previous Grape versions allowed this, though it wasn't documented:
247
+
248
+ ```ruby
249
+ requires :true_value, type: TrueClass
250
+ requires :bool_value, types: [FalseClass, TrueClass]
251
+ ```
252
+
253
+ This is no longer supported, if you do this, your values will never be valid. Instead you should do this:
254
+
255
+ ```ruby
256
+ requires :true_value, type: Boolean # in your endpoint you should validate if this is actually `true`
257
+ requires :bool_value, type: Boolean
258
+ ```
259
+
64
260
  #### Ensure that Array types have explicit coercions
65
261
 
66
- Unlike Virtus, dry-types does not perform any implict coercions. If you
67
- have any uses of `Array[String]`, `Array[Integer]`, etc. be sure they
68
- use a `coerce_with` block. For example:
262
+ Unlike Virtus, dry-types does not perform any implict coercions. If you have any uses of `Array[String]`, `Array[Integer]`, etc. be sure they use a `coerce_with` block. For example:
69
263
 
70
264
  ```ruby
71
265
  requires :values, type: Array[String]
72
266
  ```
73
267
 
74
- It's quite common to pass a comma-separated list, such as `tag1,tag2` as
75
- `values`. Previously Virtus would implicitly coerce this to
76
- `Array(values)` so that `["tag1,tag2"]` would pass the type checks, but
77
- with `dry-types` the values are no longer coerced for you. To fix this,
78
- you might do:
268
+ It's quite common to pass a comma-separated list, such as `tag1,tag2` as `values`. Previously Virtus would implicitly coerce this to `Array(values)` so that `["tag1,tag2"]` would pass the type checks, but with `dry-types` the values are no longer coerced for you. To fix this, you might do:
79
269
 
80
270
  ```ruby
81
271
  requires :values, type: Array[String], coerce_with: ->(val) { val.split(',').map(&:strip) }
@@ -142,12 +332,9 @@ In order to make obtaining the name of a mounted class simpler, we've delegated
142
332
 
143
333
  ##### Patching the class
144
334
 
145
- In an effort to make APIs re-mountable, The class `Grape::API` no longer refers to an API instance,
146
- rather, what used to be `Grape::API` is now `Grape::API::Instance` and `Grape::API` was replaced
147
- with a class that can contain several instances of `Grape::API`.
335
+ In an effort to make APIs re-mountable, The class `Grape::API` no longer refers to an API instance, rather, what used to be `Grape::API` is now `Grape::API::Instance` and `Grape::API` was replaced with a class that can contain several instances of `Grape::API`.
148
336
 
149
- This changes were done in such a way that no code-changes should be required.
150
- However, if experiencing problems, or relying on private methods and internal behaviour too deeply, it is possible to restore the prior behaviour by replacing the references from `Grape::API` to `Grape::API::Instance`.
337
+ This changes were done in such a way that no code-changes should be required. However, if experiencing problems, or relying on private methods and internal behaviour too deeply, it is possible to restore the prior behaviour by replacing the references from `Grape::API` to `Grape::API::Instance`.
151
338
 
152
339
  Note, this is particularly relevant if you are opening the class `Grape::API` for modification.
153
340
 
@@ -170,15 +357,20 @@ end
170
357
 
171
358
  After the patch, the mounted API is no longer a Named class inheriting from `Grape::API`, it is an anonymous class
172
359
  which inherit from `Grape::API::Instance`.
360
+
173
361
  What this means in practice, is:
362
+
174
363
  - Generally: you can access the named class from the instance calling the getter `base`.
175
- - In particular: If you need the `name`, you can use `base`.`name`
364
+ - In particular: If you need the `name`, you can use `base`.`name`.
176
365
 
177
366
  **Deprecated**
367
+
178
368
  ```ruby
179
369
  payload[:endpoint].options[:for].name
180
370
  ```
371
+
181
372
  **New**
373
+
182
374
  ```ruby
183
375
  payload[:endpoint].options[:for].base.name
184
376
  ```
@@ -269,8 +461,7 @@ See [#1610](https://github.com/ruby-grape/grape/pull/1610) for more information.
269
461
 
270
462
  #### The `except`, `except_message`, and `proc` options of the `values` validator are deprecated.
271
463
 
272
- The new `except_values` validator should be used in place of the `except` and `except_message` options of
273
- the `values` validator.
464
+ The new `except_values` validator should be used in place of the `except` and `except_message` options of the `values` validator.
274
465
 
275
466
  Arity one Procs may now be used directly as the `values` option to explicitly test param values.
276
467
 
@@ -346,9 +537,7 @@ get '/example' #=> before: 405, after: 404
346
537
 
347
538
  #### Removed param processing from built-in OPTIONS handler
348
539
 
349
- When a request is made to the built-in `OPTIONS` handler, only the `before` and `after`
350
- callbacks associated with the resource will be run. The `before_validation` and
351
- `after_validation` callbacks and parameter validations will be skipped.
540
+ When a request is made to the built-in `OPTIONS` handler, only the `before` and `after` callbacks associated with the resource will be run. The `before_validation` and `after_validation` callbacks and parameter validations will be skipped.
352
541
 
353
542
  See [#1505](https://github.com/ruby-grape/grape/pull/1505) for more information.
354
543
 
@@ -369,8 +558,7 @@ See [#1510](https://github.com/ruby-grape/grape/pull/1510) for more information.
369
558
 
370
559
  #### The default status code for DELETE is now 204 instead of 200.
371
560
 
372
- Breaking change: Sets the default response status code for a delete request to 204.
373
- A status of 204 makes the response more distinguishable and therefore easier to handle on the client side, particularly because a DELETE request typically returns an empty body as the resource was deleted or voided.
561
+ Breaking change: Sets the default response status code for a delete request to 204. A status of 204 makes the response more distinguishable and therefore easier to handle on the client side, particularly because a DELETE request typically returns an empty body as the resource was deleted or voided.
374
562
 
375
563
  To achieve the old behavior, one has to set it explicitly:
376
564
  ```ruby
@@ -548,18 +736,14 @@ See [#1114](https://github.com/ruby-grape/grape/pull/1114) for more information.
548
736
 
549
737
  #### Bypasses formatters when status code indicates no content
550
738
 
551
- To be consistent with rack and it's handling of standard responses
552
- associated with no content, both default and custom formatters will now
739
+ To be consistent with rack and it's handling of standard responses associated with no content, both default and custom formatters will now
553
740
  be bypassed when processing responses for status codes defined [by rack](https://github.com/rack/rack/blob/master/lib/rack/utils.rb#L567)
554
741
 
555
742
  See [#1190](https://github.com/ruby-grape/grape/pull/1190) for more information.
556
743
 
557
744
  #### Redirects respond as plain text with message
558
745
 
559
- `#redirect` now uses `text/plain` regardless of whether that format has
560
- been enabled. This prevents formatters from attempting to serialize the
561
- message body and allows for a descriptive message body to be provided - and
562
- optionally overridden - that better fulfills the theme of the HTTP spec.
746
+ `#redirect` now uses `text/plain` regardless of whether that format has been enabled. This prevents formatters from attempting to serialize the message body and allows for a descriptive message body to be provided - and optionally overridden - that better fulfills the theme of the HTTP spec.
563
747
 
564
748
  See [#1194](https://github.com/ruby-grape/grape/pull/1194) for more information.
565
749
 
@@ -593,10 +777,7 @@ end
593
777
 
594
778
  See [#1029](https://github.com/ruby-grape/grape/pull/1029) for more information.
595
779
 
596
- There is a known issue because of this change. When Grape is used with an older
597
- than 1.2.4 version of [warden](https://github.com/hassox/warden) there may be raised
598
- the following exception having the [rack-mount](https://github.com/jm/rack-mount) gem's
599
- lines as last ones in the backtrace:
780
+ There is a known issue because of this change. When Grape is used with an older than 1.2.4 version of [warden](https://github.com/hassox/warden) there may be raised the following exception having the [rack-mount](https://github.com/jm/rack-mount) gem's lines as last ones in the backtrace:
600
781
 
601
782
  ```
602
783
  NoMethodError: undefined method `[]' for nil:NilClass