grape 1.0.2 → 1.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: 22167fc7407088f03f9c85cc9e9ab6f63186e30a9c41cff89ca042a71a7dbdf7
4
- data.tar.gz: 9ba03eae4067052f0d10dcefb032bc15f8844221e31397ed03398b4a4dbcda5d
2
+ SHA1:
3
+ metadata.gz: 5e2e2a2c3e1ed64c7c75af7d0fb52467c4e596a9
4
+ data.tar.gz: a23ce793ad55115be0300f310f7ec024769275e8
5
5
  SHA512:
6
- metadata.gz: a206dba0bd582138f92d3020c98b4019095175d3c4412d650b4a994f3b2881a2f24867a32c6c7163c5fd589a3b2ccbfdef9453ca3d70b726c62bcdf094a463f7
7
- data.tar.gz: 92c1e9d3c7d89a93c5ce8c9bb9a28baed795f99de0d495dfac9968dabd810621665162d78fdcd0ed846f0a9b83bd02b163de768bc7059843d0bea67fd65d6502
6
+ metadata.gz: e754bfdf8d83d12ed4e770114a3a8b5e80ca2462be2d13cbbd68a15b5c528856d897715f630f381460bc4cdc4f2715dffd24945c5c510db397183f79a281af11
7
+ data.tar.gz: 25da8c7eb6ef92e5ea4ac55103fb688738f3544818b6a971408f150fab4392bbe8e0e0f2a1be56cf47e0a121aabf790bd4389876ee9dfc11c00b6b77920a40ff
@@ -1,3 +1,16 @@
1
+ ### 1.0.3 (4/23/2018)
2
+
3
+ #### Fixes
4
+
5
+ * [#1755](https://github.com/ruby-grape/grape/pull/1755): Fix shared params with exactly_one_of - [@milgner](https://github.com/milgner).
6
+ * [#1740](https://github.com/ruby-grape/grape/pull/1740): Fix dependent parameter validation using `given` when parameter is a `Hash` - [@jvortmann](https://github.com/jvortmann).
7
+ * [#1737](https://github.com/ruby-grape/grape/pull/1737): Fix translating error when passing symbols as params in custom validations - [@mlzhuyi](https://github.com/mlzhuyi).
8
+ * [#1749](https://github.com/ruby-grape/grape/pull/1749): Allow rescue from non-`StandardError` exceptions - [@dm1try](https://github.com/dm1try).
9
+ * [#1750](https://github.com/ruby-grape/grape/pull/1750): Fix a circular dependency warning due to router being loaded by API - [@salasrod](https://github.com/salasrod).
10
+ * [#1752](https://github.com/ruby-grape/grape/pull/1752): Fix `include_missing` behavior for aliased parameters - [@jonasoberschweiber](https://github.com/jonasoberschweiber).
11
+ * [#1754](https://github.com/ruby-grape/grape/pull/1754): Allow rescue from non-`StandardError` exceptions to use default error handling - [@jelkster](https://github.com/jelkster).
12
+ * [#1756](https://github.com/ruby-grape/grape/pull/1756): Allow custom Grape exception handlers when the built-in exception handling is enabled - [@soylent](https://github.com/soylent).
13
+
1
14
  ### 1.0.2 (1/10/2018)
2
15
 
3
16
  #### Features
data/Gemfile CHANGED
@@ -22,7 +22,7 @@ end
22
22
  group :test do
23
23
  gem 'cookiejar'
24
24
  gem 'coveralls', '~> 0.8.17', require: false
25
- gem 'danger-toc', '~> 0.1.0'
25
+ gem 'danger-toc', '~> 0.1.2'
26
26
  gem 'grape-entity', '~> 0.6'
27
27
  gem 'maruku'
28
28
  gem 'mime-types'
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- grape (1.0.2)
4
+ grape (1.0.3)
5
5
  activesupport
6
6
  builder
7
7
  mustermann-grape (~> 1.0.0)
@@ -23,7 +23,7 @@ GEM
23
23
  bundler
24
24
  rake
25
25
  thor (>= 0.14.0)
26
- ast (2.3.0)
26
+ ast (2.4.0)
27
27
  axiom-types (0.1.1)
28
28
  descendants_tracker (~> 0.0.4)
29
29
  ice_nine (~> 0.11.0)
@@ -65,7 +65,7 @@ GEM
65
65
  danger-plugin-api (~> 1.0)
66
66
  danger-plugin-api (1.0.0)
67
67
  danger (> 2.0)
68
- danger-toc (0.1.0)
68
+ danger-toc (0.1.2)
69
69
  activesupport
70
70
  danger-plugin-api (~> 1.0)
71
71
  kramdown
@@ -74,15 +74,15 @@ GEM
74
74
  diff-lcs (1.3)
75
75
  docile (1.1.5)
76
76
  equalizer (0.0.11)
77
- faraday (0.13.1)
77
+ faraday (0.14.0)
78
78
  multipart-post (>= 1.2, < 3)
79
79
  faraday-http-cache (1.3.1)
80
80
  faraday (~> 0.8)
81
- ffi (1.9.18)
81
+ ffi (1.9.21)
82
82
  formatador (0.2.5)
83
83
  git (1.3.0)
84
- grape-entity (0.6.1)
85
- activesupport (>= 5.0.0)
84
+ grape-entity (0.7.1)
85
+ activesupport (>= 4.0)
86
86
  multi_json (>= 1.3.2)
87
87
  guard (2.14.2)
88
88
  formatador (>= 0.2.4)
@@ -102,7 +102,7 @@ GEM
102
102
  guard (~> 2.0)
103
103
  rubocop (~> 0.20)
104
104
  hashie (3.5.7)
105
- i18n (0.9.1)
105
+ i18n (0.9.4)
106
106
  concurrent-ruby (~> 1.0)
107
107
  ice_nine (0.11.2)
108
108
  json (2.1.0)
@@ -117,7 +117,7 @@ GEM
117
117
  mime-types (3.1)
118
118
  mime-types-data (~> 3.2015)
119
119
  mime-types-data (3.2016.0521)
120
- minitest (5.11.1)
120
+ minitest (5.11.3)
121
121
  multi_json (1.13.1)
122
122
  multipart-post (2.0.0)
123
123
  mustermann (1.0.1)
@@ -139,7 +139,7 @@ GEM
139
139
  coderay (~> 1.1.0)
140
140
  method_source (~> 0.9.0)
141
141
  public_suffix (3.0.1)
142
- rack (2.0.3)
142
+ rack (2.0.4)
143
143
  rack-accept (0.4.5)
144
144
  rack (>= 0.4)
145
145
  rack-jsonp (1.3.1)
@@ -164,7 +164,7 @@ GEM
164
164
  rspec-mocks (3.7.0)
165
165
  diff-lcs (>= 1.2.0, < 2.0)
166
166
  rspec-support (~> 3.7.0)
167
- rspec-support (3.7.0)
167
+ rspec-support (3.7.1)
168
168
  rubocop (0.51.0)
169
169
  parallel (~> 1.10)
170
170
  parser (>= 2.3.3.1, < 3.0)
@@ -193,7 +193,7 @@ GEM
193
193
  thor (0.19.4)
194
194
  thread_safe (0.3.6)
195
195
  tins (1.16.3)
196
- tzinfo (1.2.4)
196
+ tzinfo (1.2.5)
197
197
  thread_safe (~> 0.1)
198
198
  unicode-display_width (1.3.0)
199
199
  virtus (1.0.5)
@@ -211,7 +211,7 @@ DEPENDENCIES
211
211
  bundler
212
212
  cookiejar
213
213
  coveralls (~> 0.8.17)
214
- danger-toc (~> 0.1.0)
214
+ danger-toc (~> 0.1.2)
215
215
  grape!
216
216
  grape-entity (~> 0.6)
217
217
  guard
@@ -228,4 +228,4 @@ DEPENDENCIES
228
228
  ruby-grape-danger (~> 0.1.0)
229
229
 
230
230
  BUNDLED WITH
231
- 1.16.0
231
+ 1.15.3
data/README.md CHANGED
@@ -45,24 +45,31 @@
45
45
  - [Group Options](#group-options)
46
46
  - [Alias](#alias)
47
47
  - [Built-in Validators](#built-in-validators)
48
- - [`allow_blank`](#allowblank)
48
+ - [`allow_blank`](#allow_blank)
49
49
  - [`values`](#values)
50
- - [`except_values`](#exceptvalues)
50
+ - [`except_values`](#except_values)
51
51
  - [`regexp`](#regexp)
52
- - [`mutually_exclusive`](#mutuallyexclusive)
53
- - [`exactly_one_of`](#exactlyoneof)
54
- - [`at_least_one_of`](#atleastoneof)
55
- - [`all_or_none_of`](#allornoneof)
56
- - [Nested `mutually_exclusive`, `exactly_one_of`, `at_least_one_of`, `all_or_none_of`](#nested-mutuallyexclusive-exactlyoneof-atleastoneof-allornoneof)
52
+ - [`mutually_exclusive`](#mutually_exclusive)
53
+ - [`exactly_one_of`](#exactly_one_of)
54
+ - [`at_least_one_of`](#at_least_one_of)
55
+ - [`all_or_none_of`](#all_or_none_of)
56
+ - [Nested `mutually_exclusive`, `exactly_one_of`, `at_least_one_of`, `all_or_none_of`](#nested-mutually_exclusive-exactly_one_of-at_least_one_of-all_or_none_of)
57
57
  - [Namespace Validation and Coercion](#namespace-validation-and-coercion)
58
58
  - [Custom Validators](#custom-validators)
59
59
  - [Validation Errors](#validation-errors)
60
60
  - [I18n](#i18n)
61
61
  - [Custom Validation messages](#custom-validation-messages)
62
- - [`presence`, `allow_blank`, `values`, `regexp`](#presence-allowblank-values-regexp)
63
- - [`mutually_exclusive`](#mutuallyexclusive-1)
62
+ - [`presence`, `allow_blank`, `values`, `regexp`](#presence-allow_blank-values-regexp)
63
+ - [`all_or_none_of`](#all_or_none_of-1)
64
+ - [`mutually_exclusive`](#mutually_exclusive-1)
65
+ - [`exactly_one_of`](#exactly_one_of-1)
66
+ - [`at_least_one_of`](#at_least_one_of-1)
67
+ - [`Coerce`](#coerce)
68
+ - [`With Lambdas`](#with-lambdas)
69
+ - [`Pass symbols for i18n translations`](#pass-symbols-for-i18n-translations)
64
70
  - [Overriding Attribute Names](#overriding-attribute-names)
65
71
  - [With Default](#with-default)
72
+ - [Headers](#headers)
66
73
  - [Routes](#routes)
67
74
  - [Helpers](#helpers)
68
75
  - [Path Helpers](#path-helpers)
@@ -78,6 +85,7 @@
78
85
  - [Exception Handling](#exception-handling)
79
86
  - [Rescuing exceptions inside namespaces](#rescuing-exceptions-inside-namespaces)
80
87
  - [Unrescuable Exceptions](#unrescuable-exceptions)
88
+ - [Exceptions that should be rescued explicitly](#exceptions-that-should-be-rescued-explicitly)
81
89
  - [Rails 3.x](#rails-3x)
82
90
  - [Logging](#logging)
83
91
  - [API Formats](#api-formats)
@@ -117,10 +125,10 @@
117
125
  - [Reloading in Rails Applications](#reloading-in-rails-applications)
118
126
  - [Performance Monitoring](#performance-monitoring)
119
127
  - [Active Support Instrumentation](#active-support-instrumentation)
120
- - [endpoint_run.grape](#endpointrungrape)
121
- - [endpoint_render.grape](#endpointrendergrape)
122
- - [endpoint_run_filters.grape](#endpointrunfiltersgrape)
123
- - [endpoint_run_validators.grape](#endpointrunvalidatorsgrape)
128
+ - [endpoint_run.grape](#endpoint_rungrape)
129
+ - [endpoint_render.grape](#endpoint_rendergrape)
130
+ - [endpoint_run_filters.grape](#endpoint_run_filtersgrape)
131
+ - [endpoint_run_validators.grape](#endpoint_run_validatorsgrape)
124
132
  - [Monitoring Products](#monitoring-products)
125
133
  - [Contributing to Grape](#contributing-to-grape)
126
134
  - [License](#license)
@@ -136,7 +144,7 @@ content negotiation, versioning and much more.
136
144
 
137
145
  ## Stable Release
138
146
 
139
- You're reading the documentation for the stable release of Grape, **1.0.2**.
147
+ You're reading the documentation for the stable release of Grape, **1.0.3**.
140
148
  Please read [UPGRADING](UPGRADING.md) when upgrading from a previous version.
141
149
 
142
150
  ## Project Resources
@@ -1548,6 +1556,7 @@ params do
1548
1556
  requires :name, values: { value: 1..10, message: 'not in range from 1 to 10' }, allow_blank: { value: false, message: 'cannot be blank' }, regexp: { value: /^[a-z]+$/, message: 'format is invalid' }, message: 'is required'
1549
1557
  end
1550
1558
  ```
1559
+
1551
1560
  #### `all_or_none_of`
1552
1561
 
1553
1562
  ```ruby
@@ -1569,6 +1578,7 @@ params do
1569
1578
  mutually_exclusive :beer, :wine, :juice, message: "are mutually exclusive cannot pass both params"
1570
1579
  end
1571
1580
  ```
1581
+
1572
1582
  #### `exactly_one_of`
1573
1583
 
1574
1584
  ```ruby
@@ -1579,6 +1589,7 @@ params do
1579
1589
  exactly_one_of :beer, :wine, :juice, message: {exactly_one: "are missing, exactly one parameter is required", mutual_exclusion: "are mutually exclusive, exactly one parameter is required"}
1580
1590
  end
1581
1591
  ```
1592
+
1582
1593
  #### `at_least_one_of`
1583
1594
 
1584
1595
  ```ruby
@@ -1589,6 +1600,7 @@ params do
1589
1600
  at_least_one_of :beer, :wine, :juice, message: "are missing, please specify at least one param"
1590
1601
  end
1591
1602
  ```
1603
+
1592
1604
  #### `Coerce`
1593
1605
 
1594
1606
  ```ruby
@@ -1596,6 +1608,7 @@ params do
1596
1608
  requires :int, type: {value: Integer, message: "type cast is invalid" }
1597
1609
  end
1598
1610
  ```
1611
+
1599
1612
  #### `With Lambdas`
1600
1613
 
1601
1614
  ```ruby
@@ -1603,6 +1616,7 @@ params do
1603
1616
  requires :name, values: { value: -> { (1..10).to_a }, message: 'not in range from 1 to 10' }
1604
1617
  end
1605
1618
  ```
1619
+
1606
1620
  #### `Pass symbols for i18n translations`
1607
1621
 
1608
1622
  You can pass a symbol if you want i18n translations for your custom validation messages.
@@ -1650,6 +1664,7 @@ params do
1650
1664
  requires :name, values: { value: -> { (1..10).to_a }, message: 'not in range from 1 to 10' }, default: 5
1651
1665
  end
1652
1666
  ```
1667
+
1653
1668
  ## Headers
1654
1669
 
1655
1670
  Request headers are available through the `headers` helper or from `env` in their original form.
@@ -2078,6 +2093,9 @@ class Twitter::API < Grape::API
2078
2093
  end
2079
2094
  ```
2080
2095
 
2096
+ This mimics [default `rescue` behaviour](https://ruby-doc.org/core/StandardError.html) when an exception type is not provided.
2097
+ Any other exception should be rescued explicitly, see [below](#exceptions-that-should-be-rescued-explicitly).
2098
+
2081
2099
  Grape can also rescue from all exceptions and still use the built-in exception handing.
2082
2100
  This will give the same behavior as `rescue_from :all` with the addition that Grape will use the exception handling defined by all Exception classes that inherit `Grape::Exceptions::Base`.
2083
2101
 
@@ -2280,6 +2298,12 @@ Here `'inner'` will be result of handling occured `ArgumentError`.
2280
2298
 
2281
2299
  `Grape::Exceptions::InvalidVersionHeader`, which is raised when the version in the request header doesn't match the currently evaluated version for the endpoint, will _never_ be rescued from a `rescue_from` block (even a `rescue_from :all`) This is because Grape relies on Rack to catch that error and try the next versioned-route for cases where there exist identical Grape endpoints with different versions.
2282
2300
 
2301
+ #### Exceptions that should be rescued explicitly
2302
+
2303
+ Any exception that is not subclass of `StandardError` should be rescued explicitly.
2304
+ Usually it is not a case for an application logic as such errors point to problems in Ruby runtime.
2305
+ This is following [standard recommendations for exceptions handling](https://ruby-doc.org/core/Exception.html).
2306
+
2283
2307
  ### Rails 3.x
2284
2308
 
2285
2309
  When mounted inside containers, such as Rails 3.x, errors such as "404 Not Found" or
@@ -30,7 +30,6 @@ module Grape
30
30
  eager_autoload do
31
31
  autoload :API
32
32
  autoload :Endpoint
33
- autoload :Router
34
33
 
35
34
  autoload :Namespace
36
35
 
@@ -64,7 +64,7 @@ module Grape
64
64
  has_alias = route_setting(:aliased_params) && route_setting(:aliased_params).find { |current| current[declared_param] }
65
65
  param_alias = has_alias[declared_param] if has_alias
66
66
 
67
- next unless options[:include_missing] || passed_params.key?(declared_param) || param_alias
67
+ next unless options[:include_missing] || passed_params.key?(declared_param) || (param_alias && passed_params.key?(param_alias))
68
68
 
69
69
  if param_alias
70
70
  memo[optioned_param_key(param_alias, options)] = passed_params[param_alias]
@@ -201,7 +201,7 @@ module Grape
201
201
  # @yield a parameter definition DSL
202
202
  def given(*attrs, &block)
203
203
  attrs.each do |attr|
204
- proxy_attr = attr.is_a?(Hash) ? attr.keys[0] : attr
204
+ proxy_attr = first_hash_key_or_param(attr)
205
205
  raise Grape::Exceptions::UnknownParameter.new(proxy_attr) unless declared_param?(proxy_attr)
206
206
  end
207
207
  new_lateral_scope(dependent_on: attrs, &block)
@@ -213,7 +213,9 @@ module Grape
213
213
  def declared_param?(param)
214
214
  # @declared_params also includes hashes of options and such, but those
215
215
  # won't be flattened out.
216
- @declared_params.flatten.include?(param)
216
+ @declared_params.flatten.any? do |declared_param|
217
+ first_hash_key_or_param(declared_param) == param
218
+ end
217
219
  end
218
220
 
219
221
  alias group requires
@@ -238,6 +240,12 @@ module Grape
238
240
  params = map_params(params, @element) if @element
239
241
  params
240
242
  end
243
+
244
+ private
245
+
246
+ def first_hash_key_or_param(parameter)
247
+ parameter.is_a?(Hash) ? parameter.keys.first : parameter
248
+ end
241
249
  end
242
250
  end
243
251
  end
@@ -71,6 +71,8 @@ module Grape
71
71
  end
72
72
 
73
73
  def translate(key, **options)
74
+ options = options.dup
75
+ options[:default] &&= options[:default].to_s
74
76
  message = ::I18n.translate(key, **options)
75
77
  message.present? ? message : ::I18n.translate(key, locale: FALLBACK_LOCALE, **options)
76
78
  end
@@ -36,47 +36,15 @@ module Grape
36
36
  error_response(catch(:error) do
37
37
  return @app.call(@env)
38
38
  end)
39
- rescue StandardError => e
40
- is_rescuable = rescuable?(e.class)
41
- if e.is_a?(Grape::Exceptions::Base) && (!is_rescuable || rescuable_by_grape?(e.class))
42
- handler = ->(arg) { error_response(arg) }
43
- else
44
- raise unless is_rescuable
45
- handler = find_handler(e.class)
46
- end
47
-
48
- handler.nil? ? handle_error(e) : exec_handler(e, &handler)
49
- end
50
- end
51
-
52
- def find_handler(klass)
53
- handler = options[:rescue_handlers].find(-> { [] }) { |error, _| klass <= error }[1]
54
- handler ||= options[:base_only_rescue_handlers][klass]
55
- handler ||= options[:all_rescue_handler]
56
-
57
- if handler.instance_of?(Symbol)
58
- raise NoMethodError, "undefined method `#{handler}'" unless respond_to?(handler)
59
- handler = self.class.instance_method(handler).bind(self)
60
- end
61
-
62
- handler
63
- end
64
-
65
- def rescuable?(klass)
66
- return false if klass == Grape::Exceptions::InvalidVersionHeader
67
- rescue_all? || rescue_class_or_its_ancestor?(klass) || rescue_with_base_only_handler?(klass)
68
- end
69
-
70
- def rescuable_by_grape?(klass)
71
- return false if klass == Grape::Exceptions::InvalidVersionHeader
72
- options[:rescue_grape_exceptions]
73
- end
74
-
75
- def exec_handler(e, &handler)
76
- if handler.lambda? && handler.arity.zero?
77
- instance_exec(&handler)
78
- else
79
- instance_exec(e, &handler)
39
+ rescue Exception => error # rubocop:disable Lint/RescueException
40
+ handler =
41
+ rescue_handler_for_base_only_class(error.class) ||
42
+ rescue_handler_for_class_or_its_ancestor(error.class) ||
43
+ rescue_handler_for_grape_exception(error.class) ||
44
+ rescue_handler_for_any_class(error.class) ||
45
+ raise
46
+
47
+ run_rescue_handler(handler, error)
80
48
  end
81
49
  end
82
50
 
@@ -85,7 +53,7 @@ module Grape
85
53
  rack_response(format_message(message, backtrace, original_exception), status, headers)
86
54
  end
87
55
 
88
- def handle_error(e)
56
+ def default_rescue_handler(e)
89
57
  error_response(message: e.message, backtrace: e.backtrace, original_exception: e)
90
58
  end
91
59
 
@@ -117,16 +85,45 @@ module Grape
117
85
 
118
86
  private
119
87
 
120
- def rescue_all?
121
- options[:rescue_all]
88
+ def rescue_handler_for_base_only_class(klass)
89
+ error, handler = options[:base_only_rescue_handlers].find { |err, _handler| klass == err }
90
+
91
+ return unless error
92
+
93
+ handler || :default_rescue_handler
94
+ end
95
+
96
+ def rescue_handler_for_class_or_its_ancestor(klass)
97
+ error, handler = options[:rescue_handlers].find { |err, _handler| klass <= err }
98
+
99
+ return unless error
100
+
101
+ handler || :default_rescue_handler
102
+ end
103
+
104
+ def rescue_handler_for_grape_exception(klass)
105
+ return unless klass <= Grape::Exceptions::Base
106
+ return :error_response if klass == Grape::Exceptions::InvalidVersionHeader
107
+ return unless options[:rescue_grape_exceptions] || !options[:rescue_all]
108
+
109
+ :error_response
122
110
  end
123
111
 
124
- def rescue_class_or_its_ancestor?(klass)
125
- (options[:rescue_handlers] || []).any? { |error, _handler| klass <= error }
112
+ def rescue_handler_for_any_class(klass)
113
+ return unless klass <= StandardError
114
+ return unless options[:rescue_all] || options[:rescue_grape_exceptions]
115
+
116
+ options[:all_rescue_handler] || :default_rescue_handler
126
117
  end
127
118
 
128
- def rescue_with_base_only_handler?(klass)
129
- (options[:base_only_rescue_handlers] || []).include?(klass)
119
+ def run_rescue_handler(handler, error)
120
+ if handler.instance_of?(Symbol)
121
+ raise NoMethodError, "undefined method `#{handler}'" unless respond_to?(handler)
122
+
123
+ handler = public_method(handler)
124
+ end
125
+
126
+ handler.arity.zero? ? instance_exec(&handler) : instance_exec(error, &handler)
130
127
  end
131
128
  end
132
129
  end
@@ -40,7 +40,7 @@ module Grape
40
40
  # validated
41
41
  def should_validate?(parameters)
42
42
  return false if @optional && (params(parameters).blank? || all_element_blank?(parameters))
43
-
43
+ return false unless meets_dependency?(params(parameters), parameters)
44
44
  return true if parent.nil?
45
45
  parent.should_validate?(parameters)
46
46
  end
@@ -51,7 +51,7 @@ module Grape
51
51
  end
52
52
 
53
53
  return true unless @dependent_on
54
-
54
+ return params.any? { |param| meets_dependency?(param, request_params) } if params.is_a?(Array)
55
55
  params = params.with_indifferent_access
56
56
 
57
57
  @dependent_on.each do |dependency|
@@ -1,4 +1,4 @@
1
1
  module Grape
2
2
  # The current version of Grape.
3
- VERSION = '1.0.2'.freeze
3
+ VERSION = '1.0.3'.freeze
4
4
  end
Binary file
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ describe Grape::API::Helpers do
4
+ subject do
5
+ shared_params = Module.new do
6
+ extend Grape::API::Helpers
7
+
8
+ params :drink do
9
+ optional :beer
10
+ optional :wine
11
+ exactly_one_of :beer, :wine
12
+ end
13
+ end
14
+
15
+ Class.new(Grape::API) do
16
+ helpers shared_params
17
+ format :json
18
+
19
+ params do
20
+ requires :orderType, type: String, values: %w[food drink]
21
+ given orderType: ->(val) { val == 'food' } do
22
+ optional :pasta
23
+ optional :pizza
24
+ exactly_one_of :pasta, :pizza
25
+ end
26
+ given orderType: ->(val) { val == 'drink' } do
27
+ use :drink
28
+ end
29
+ end
30
+ get do
31
+ declared(params, include_missing: true)
32
+ end
33
+ end
34
+ end
35
+
36
+ def app
37
+ subject
38
+ end
39
+
40
+ it 'defines parameters' do
41
+ get '/', orderType: 'food', pizza: 'mista'
42
+ expect(last_response.status).to eq 200
43
+ expect(last_response.body).to eq({ orderType: 'food',
44
+ pasta: nil, pizza: 'mista',
45
+ beer: nil, wine: nil }.to_json)
46
+ end
47
+ end
@@ -1946,6 +1946,40 @@ XML
1946
1946
  end
1947
1947
  end
1948
1948
 
1949
+ describe '.rescue_from :grape_exceptions' do
1950
+ before do
1951
+ subject.rescue_from :grape_exceptions
1952
+ end
1953
+
1954
+ let(:grape_exception) do
1955
+ Grape::Exceptions::Base.new(status: 400, message: 'Grape Error')
1956
+ end
1957
+
1958
+ it 'rescues grape exceptions' do
1959
+ exception = grape_exception
1960
+ subject.get('/grape_exception') { raise exception }
1961
+
1962
+ get '/grape_exception'
1963
+
1964
+ expect(last_response.status).to eq(exception.status)
1965
+ expect(last_response.body).to eq(exception.message)
1966
+ end
1967
+
1968
+ it 'rescues grape exceptions with a user-defined handler' do
1969
+ subject.rescue_from grape_exception.class do |_error|
1970
+ rack_response('Redefined Error', 403)
1971
+ end
1972
+
1973
+ exception = grape_exception
1974
+ subject.get('/grape_exception') { raise exception }
1975
+
1976
+ get '/grape_exception'
1977
+
1978
+ expect(last_response.status).to eq(403)
1979
+ expect(last_response.body).to eq('Redefined Error')
1980
+ end
1981
+ end
1982
+
1949
1983
  describe '.error_format' do
1950
1984
  it 'rescues all errors and return :txt' do
1951
1985
  subject.rescue_from :all
@@ -464,7 +464,20 @@ describe Grape::Endpoint do
464
464
 
465
465
  it 'does not include missing attributes if that option is passed' do
466
466
  subject.get '/declared' do
467
- error! 400, 'expected nil' if declared(params, include_missing: false)[:second]
467
+ error! 'expected nil', 400 if declared(params, include_missing: false).key?(:second)
468
+ ''
469
+ end
470
+
471
+ get '/declared?first=one&other=two'
472
+ expect(last_response.status).to eq(200)
473
+ end
474
+
475
+ it 'does not include aliased missing attributes if that option is passed' do
476
+ subject.params do
477
+ optional :aliased_original, as: :aliased
478
+ end
479
+ subject.get '/declared' do
480
+ error! 'expected nil', 400 if declared(params, include_missing: false).key?(:aliased)
468
481
  ''
469
482
  end
470
483
 
@@ -43,6 +43,15 @@ describe Grape::Exceptions::ValidationErrors do
43
43
  expect(subject).to contain_exactly('id is missing', 'name is missing')
44
44
  end
45
45
  end
46
+
47
+ context 'when attributes is an array of symbols' do
48
+ let(:validation_error) { Grape::Exceptions::Validation.new(params: [:admin_field], message: 'Can not set admin-only field') }
49
+ subject { described_class.new(errors: [validation_error]).full_messages }
50
+
51
+ it 'returns an array with an error full message' do
52
+ expect(subject.first).to eq('admin_field Can not set admin-only field')
53
+ end
54
+ end
46
55
  end
47
56
 
48
57
  context 'api' do
@@ -109,6 +109,36 @@ describe Grape::Middleware::Error do
109
109
  end
110
110
  end
111
111
 
112
+ context 'Non-StandardError exception with a provided rescue handler' do
113
+ context 'default error response' do
114
+ subject do
115
+ Rack::Builder.app do
116
+ use Spec::Support::EndpointFaker
117
+ use Grape::Middleware::Error, rescue_handlers: { NotImplementedError => nil }
118
+ run ExceptionSpec::OtherExceptionApp
119
+ end
120
+ end
121
+ it 'rescues the exception using the default handler' do
122
+ get '/'
123
+ expect(last_response.body).to eq('snow!')
124
+ end
125
+ end
126
+
127
+ context 'custom error response' do
128
+ subject do
129
+ Rack::Builder.app do
130
+ use Spec::Support::EndpointFaker
131
+ use Grape::Middleware::Error, rescue_handlers: { NotImplementedError => -> { [200, {}, 'rescued'] } }
132
+ run ExceptionSpec::OtherExceptionApp
133
+ end
134
+ end
135
+ it 'rescues the exception using the provided handler' do
136
+ get '/'
137
+ expect(last_response.body).to eq('rescued')
138
+ end
139
+ end
140
+ end
141
+
112
142
  context do
113
143
  subject do
114
144
  Rack::Builder.app do
@@ -466,6 +466,19 @@ describe Grape::Validations::ParamsScope do
466
466
  end.to raise_error(Grape::Exceptions::UnknownParameter)
467
467
  end
468
468
 
469
+ it 'does not raise an error if the dependent parameter is a Hash' do
470
+ expect do
471
+ subject.params do
472
+ optional :a, type: Hash do
473
+ requires :b
474
+ end
475
+ given :a do
476
+ requires :c
477
+ end
478
+ end
479
+ end.to_not raise_error
480
+ end
481
+
469
482
  it 'does not validate nested requires when given is false' do
470
483
  subject.params do
471
484
  requires :a, type: String, allow_blank: false, values: %w[x y z]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grape
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Bleigh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-01-10 00:00:00.000000000 Z
11
+ date: 2018-04-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -250,8 +250,7 @@ files:
250
250
  - lib/grape/validations/validators/regexp.rb
251
251
  - lib/grape/validations/validators/values.rb
252
252
  - lib/grape/version.rb
253
- - pkg/grape-0.19.1.gem
254
- - pkg/grape-1.0.1.gem
253
+ - pkg/grape-1.0.0.gem
255
254
  - spec/grape/api/custom_validations_spec.rb
256
255
  - spec/grape/api/deeply_included_options_spec.rb
257
256
  - spec/grape/api/inherited_helpers_spec.rb
@@ -264,6 +263,7 @@ files:
264
263
  - spec/grape/api/recognize_path_spec.rb
265
264
  - spec/grape/api/required_parameters_in_route_spec.rb
266
265
  - spec/grape/api/required_parameters_with_invalid_method_spec.rb
266
+ - spec/grape/api/shared_helpers_exactly_one_of_spec.rb
267
267
  - spec/grape/api/shared_helpers_spec.rb
268
268
  - spec/grape/api_spec.rb
269
269
  - spec/grape/dsl/callbacks_spec.rb
@@ -368,104 +368,105 @@ required_rubygems_version: !ruby/object:Gem::Requirement
368
368
  version: '0'
369
369
  requirements: []
370
370
  rubyforge_project:
371
- rubygems_version: 2.7.3
371
+ rubygems_version: 2.6.12
372
372
  signing_key:
373
373
  specification_version: 4
374
374
  summary: A simple Ruby framework for building REST-like APIs.
375
375
  test_files:
376
- - spec/grape/api/custom_validations_spec.rb
377
- - spec/grape/api/deeply_included_options_spec.rb
378
- - spec/grape/api/inherited_helpers_spec.rb
379
- - spec/grape/api/invalid_format_spec.rb
380
- - spec/grape/api/namespace_parameters_in_route_spec.rb
381
- - spec/grape/api/nested_helpers_spec.rb
382
- - spec/grape/api/optional_parameters_in_route_spec.rb
383
- - spec/grape/api/parameters_modification_spec.rb
384
- - spec/grape/api/patch_method_helpers_spec.rb
385
- - spec/grape/api/recognize_path_spec.rb
386
- - spec/grape/api/required_parameters_in_route_spec.rb
387
- - spec/grape/api/required_parameters_with_invalid_method_spec.rb
388
- - spec/grape/api/shared_helpers_spec.rb
389
- - spec/grape/api_spec.rb
390
- - spec/grape/dsl/callbacks_spec.rb
391
- - spec/grape/dsl/configuration_spec.rb
392
- - spec/grape/dsl/desc_spec.rb
393
- - spec/grape/dsl/headers_spec.rb
394
- - spec/grape/dsl/helpers_spec.rb
395
- - spec/grape/dsl/inside_route_spec.rb
396
- - spec/grape/dsl/logger_spec.rb
397
- - spec/grape/dsl/middleware_spec.rb
398
- - spec/grape/dsl/parameters_spec.rb
399
- - spec/grape/dsl/request_response_spec.rb
400
- - spec/grape/dsl/routing_spec.rb
401
- - spec/grape/dsl/settings_spec.rb
402
- - spec/grape/dsl/validations_spec.rb
403
- - spec/grape/endpoint_spec.rb
404
- - spec/grape/entity_spec.rb
405
- - spec/grape/exceptions/body_parse_errors_spec.rb
406
- - spec/grape/exceptions/invalid_accept_header_spec.rb
407
- - spec/grape/exceptions/invalid_formatter_spec.rb
408
- - spec/grape/exceptions/invalid_versioner_option_spec.rb
409
- - spec/grape/exceptions/missing_mime_type_spec.rb
410
- - spec/grape/exceptions/missing_option_spec.rb
411
- - spec/grape/exceptions/unknown_options_spec.rb
412
- - spec/grape/exceptions/unknown_validator_spec.rb
413
- - spec/grape/exceptions/validation_errors_spec.rb
414
- - spec/grape/exceptions/validation_spec.rb
415
- - spec/grape/extensions/param_builders/hash_spec.rb
416
- - spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb
417
- - spec/grape/extensions/param_builders/hashie/mash_spec.rb
418
- - spec/grape/integration/global_namespace_function_spec.rb
419
- - spec/grape/integration/rack_sendfile_spec.rb
420
- - spec/grape/integration/rack_spec.rb
421
- - spec/grape/loading_spec.rb
422
- - spec/grape/middleware/auth/base_spec.rb
423
- - spec/grape/middleware/auth/dsl_spec.rb
424
- - spec/grape/middleware/auth/strategies_spec.rb
425
- - spec/grape/middleware/base_spec.rb
376
+ - spec/spec_helper.rb
377
+ - spec/integration/multi_xml/xml_spec.rb
378
+ - spec/integration/multi_json/json_spec.rb
379
+ - spec/shared/versioning_examples.rb
380
+ - spec/support/basic_auth_encode_helpers.rb
381
+ - spec/support/endpoint_faker.rb
382
+ - spec/support/file_streamer.rb
383
+ - spec/support/versioned_helpers.rb
384
+ - spec/support/content_type_helpers.rb
385
+ - spec/support/integer_helpers.rb
426
386
  - spec/grape/middleware/error_spec.rb
427
- - spec/grape/middleware/exception_spec.rb
428
- - spec/grape/middleware/formatter_spec.rb
429
387
  - spec/grape/middleware/globals_spec.rb
388
+ - spec/grape/middleware/formatter_spec.rb
389
+ - spec/grape/middleware/auth/strategies_spec.rb
390
+ - spec/grape/middleware/auth/dsl_spec.rb
391
+ - spec/grape/middleware/auth/base_spec.rb
430
392
  - spec/grape/middleware/stack_spec.rb
393
+ - spec/grape/middleware/exception_spec.rb
394
+ - spec/grape/middleware/versioner_spec.rb
431
395
  - spec/grape/middleware/versioner/accept_version_header_spec.rb
432
396
  - spec/grape/middleware/versioner/header_spec.rb
433
- - spec/grape/middleware/versioner/param_spec.rb
434
397
  - spec/grape/middleware/versioner/path_spec.rb
435
- - spec/grape/middleware/versioner_spec.rb
436
- - spec/grape/parser_spec.rb
437
- - spec/grape/path_spec.rb
438
- - spec/grape/presenters/presenter_spec.rb
439
- - spec/grape/request_spec.rb
440
- - spec/grape/util/inheritable_setting_spec.rb
441
- - spec/grape/util/inheritable_values_spec.rb
398
+ - spec/grape/middleware/versioner/param_spec.rb
399
+ - spec/grape/middleware/base_spec.rb
400
+ - spec/grape/loading_spec.rb
401
+ - spec/grape/endpoint_spec.rb
402
+ - spec/grape/api_spec.rb
442
403
  - spec/grape/util/reverse_stackable_values_spec.rb
443
404
  - spec/grape/util/stackable_values_spec.rb
405
+ - spec/grape/util/inheritable_setting_spec.rb
444
406
  - spec/grape/util/strict_hash_configuration_spec.rb
407
+ - spec/grape/util/inheritable_values_spec.rb
408
+ - spec/grape/integration/rack_spec.rb
409
+ - spec/grape/integration/rack_sendfile_spec.rb
410
+ - spec/grape/integration/global_namespace_function_spec.rb
411
+ - spec/grape/validations_spec.rb
412
+ - spec/grape/entity_spec.rb
413
+ - spec/grape/exceptions/validation_spec.rb
414
+ - spec/grape/exceptions/invalid_accept_header_spec.rb
415
+ - spec/grape/exceptions/missing_option_spec.rb
416
+ - spec/grape/exceptions/body_parse_errors_spec.rb
417
+ - spec/grape/exceptions/invalid_formatter_spec.rb
418
+ - spec/grape/exceptions/missing_mime_type_spec.rb
419
+ - spec/grape/exceptions/unknown_options_spec.rb
420
+ - spec/grape/exceptions/validation_errors_spec.rb
421
+ - spec/grape/exceptions/unknown_validator_spec.rb
422
+ - spec/grape/exceptions/invalid_versioner_option_spec.rb
423
+ - spec/grape/presenters/presenter_spec.rb
445
424
  - spec/grape/validations/attributes_iterator_spec.rb
446
- - spec/grape/validations/instance_behaivour_spec.rb
447
425
  - spec/grape/validations/params_scope_spec.rb
426
+ - spec/grape/validations/instance_behaivour_spec.rb
448
427
  - spec/grape/validations/types_spec.rb
449
- - spec/grape/validations/validators/all_or_none_spec.rb
450
- - spec/grape/validations/validators/allow_blank_spec.rb
451
- - spec/grape/validations/validators/at_least_one_of_spec.rb
452
- - spec/grape/validations/validators/coerce_spec.rb
453
- - spec/grape/validations/validators/default_spec.rb
428
+ - spec/grape/validations/validators/regexp_spec.rb
429
+ - spec/grape/validations/validators/mutual_exclusion_spec.rb
454
430
  - spec/grape/validations/validators/exactly_one_of_spec.rb
455
431
  - spec/grape/validations/validators/except_values_spec.rb
456
- - spec/grape/validations/validators/mutual_exclusion_spec.rb
457
432
  - spec/grape/validations/validators/presence_spec.rb
458
- - spec/grape/validations/validators/regexp_spec.rb
433
+ - spec/grape/validations/validators/all_or_none_spec.rb
434
+ - spec/grape/validations/validators/allow_blank_spec.rb
435
+ - spec/grape/validations/validators/default_spec.rb
459
436
  - spec/grape/validations/validators/values_spec.rb
437
+ - spec/grape/validations/validators/at_least_one_of_spec.rb
438
+ - spec/grape/validations/validators/coerce_spec.rb
460
439
  - spec/grape/validations/validators/zh-CN.yml
461
- - spec/grape/validations_spec.rb
462
- - spec/integration/multi_json/json_spec.rb
463
- - spec/integration/multi_xml/xml_spec.rb
464
- - spec/shared/versioning_examples.rb
465
- - spec/spec_helper.rb
466
- - spec/support/basic_auth_encode_helpers.rb
467
- - spec/support/content_type_helpers.rb
468
- - spec/support/endpoint_faker.rb
469
- - spec/support/file_streamer.rb
470
- - spec/support/integer_helpers.rb
471
- - spec/support/versioned_helpers.rb
440
+ - spec/grape/extensions/param_builders/hashie/mash_spec.rb
441
+ - spec/grape/extensions/param_builders/hash_spec.rb
442
+ - spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb
443
+ - spec/grape/parser_spec.rb
444
+ - spec/grape/request_spec.rb
445
+ - spec/grape/api/parameters_modification_spec.rb
446
+ - spec/grape/api/patch_method_helpers_spec.rb
447
+ - spec/grape/api/required_parameters_with_invalid_method_spec.rb
448
+ - spec/grape/api/nested_helpers_spec.rb
449
+ - spec/grape/api/invalid_format_spec.rb
450
+ - spec/grape/api/required_parameters_in_route_spec.rb
451
+ - spec/grape/api/namespace_parameters_in_route_spec.rb
452
+ - spec/grape/api/recognize_path_spec.rb
453
+ - spec/grape/api/shared_helpers_exactly_one_of_spec.rb
454
+ - spec/grape/api/inherited_helpers_spec.rb
455
+ - spec/grape/api/shared_helpers_spec.rb
456
+ - spec/grape/api/deeply_included_options_spec.rb
457
+ - spec/grape/api/custom_validations_spec.rb
458
+ - spec/grape/api/optional_parameters_in_route_spec.rb
459
+ - spec/grape/dsl/request_response_spec.rb
460
+ - spec/grape/dsl/desc_spec.rb
461
+ - spec/grape/dsl/logger_spec.rb
462
+ - spec/grape/dsl/configuration_spec.rb
463
+ - spec/grape/dsl/validations_spec.rb
464
+ - spec/grape/dsl/parameters_spec.rb
465
+ - spec/grape/dsl/helpers_spec.rb
466
+ - spec/grape/dsl/middleware_spec.rb
467
+ - spec/grape/dsl/headers_spec.rb
468
+ - spec/grape/dsl/callbacks_spec.rb
469
+ - spec/grape/dsl/settings_spec.rb
470
+ - spec/grape/dsl/routing_spec.rb
471
+ - spec/grape/dsl/inside_route_spec.rb
472
+ - spec/grape/path_spec.rb
Binary file
Binary file