grape 0.19.2 → 1.0.0

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

Potentially problematic release.


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

Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/Appraisals +8 -0
  3. data/CHANGELOG.md +40 -22
  4. data/Gemfile +1 -0
  5. data/Gemfile.lock +58 -59
  6. data/LICENSE +1 -1
  7. data/README.md +94 -49
  8. data/Rakefile +1 -0
  9. data/UPGRADING.md +89 -0
  10. data/benchmark/simple_with_type_coercer.rb +22 -0
  11. data/gemfiles/multi_json.gemfile +36 -0
  12. data/gemfiles/multi_xml.gemfile +36 -0
  13. data/gemfiles/rack_1.5.2.gemfile +1 -0
  14. data/gemfiles/rack_edge.gemfile +1 -0
  15. data/gemfiles/rails_3.gemfile +1 -0
  16. data/gemfiles/rails_4.gemfile +1 -0
  17. data/gemfiles/rails_5.gemfile +1 -0
  18. data/gemfiles/rails_edge.gemfile +1 -0
  19. data/grape.gemspec +0 -3
  20. data/lib/grape.rb +40 -17
  21. data/lib/grape/dsl/helpers.rb +32 -18
  22. data/lib/grape/dsl/inside_route.rb +2 -2
  23. data/lib/grape/dsl/parameters.rb +26 -0
  24. data/lib/grape/dsl/routing.rb +1 -1
  25. data/lib/grape/dsl/settings.rb +1 -1
  26. data/lib/grape/endpoint.rb +20 -16
  27. data/lib/grape/error_formatter/json.rb +1 -1
  28. data/lib/grape/error_formatter/txt.rb +1 -1
  29. data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +26 -0
  30. data/lib/grape/extensions/deep_hash_with_indifferent_access.rb +18 -0
  31. data/lib/grape/extensions/deep_mergeable_hash.rb +19 -0
  32. data/lib/grape/extensions/deep_symbolize_hash.rb +30 -0
  33. data/lib/grape/extensions/hash.rb +23 -0
  34. data/lib/grape/extensions/hashie/mash.rb +24 -0
  35. data/lib/grape/formatter/json.rb +1 -1
  36. data/lib/grape/formatter/serializable_hash.rb +2 -2
  37. data/lib/grape/locale/en.yml +1 -1
  38. data/lib/grape/middleware/globals.rb +1 -1
  39. data/lib/grape/parser/json.rb +2 -2
  40. data/lib/grape/parser/xml.rb +2 -2
  41. data/lib/grape/request.rb +11 -10
  42. data/lib/grape/util/json.rb +8 -0
  43. data/lib/grape/util/xml.rb +8 -0
  44. data/lib/grape/validations.rb +4 -0
  45. data/lib/grape/validations/params_scope.rb +77 -39
  46. data/lib/grape/validations/types/build_coercer.rb +27 -0
  47. data/lib/grape/validations/types/custom_type_coercer.rb +18 -4
  48. data/lib/grape/validations/types/file.rb +2 -3
  49. data/lib/grape/validations/validator_factory.rb +18 -0
  50. data/lib/grape/validations/validators/base.rb +4 -5
  51. data/lib/grape/validations/validators/coerce.rb +4 -0
  52. data/lib/grape/validations/validators/except_values.rb +20 -0
  53. data/lib/grape/validations/validators/values.rb +25 -5
  54. data/lib/grape/version.rb +1 -1
  55. data/spec/grape/api/invalid_format_spec.rb +3 -3
  56. data/spec/grape/api_spec.rb +28 -16
  57. data/spec/grape/dsl/helpers_spec.rb +25 -6
  58. data/spec/grape/endpoint_spec.rb +117 -13
  59. data/spec/grape/extensions/param_builders/hash_spec.rb +83 -0
  60. data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +105 -0
  61. data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +79 -0
  62. data/spec/grape/middleware/formatter_spec.rb +6 -2
  63. data/spec/grape/request_spec.rb +13 -3
  64. data/spec/grape/validations/instance_behaivour_spec.rb +44 -0
  65. data/spec/grape/validations/params_scope_spec.rb +23 -0
  66. data/spec/grape/validations/types_spec.rb +19 -0
  67. data/spec/grape/validations/validators/coerce_spec.rb +117 -8
  68. data/spec/grape/validations/validators/except_values_spec.rb +191 -0
  69. data/spec/grape/validations/validators/values_spec.rb +78 -0
  70. data/spec/integration/multi_json/json_spec.rb +7 -0
  71. data/spec/integration/multi_xml/xml_spec.rb +7 -0
  72. metadata +30 -46
  73. data/pkg/grape-0.18.0.gem +0 -0
data/Rakefile CHANGED
@@ -7,6 +7,7 @@ Bundler::GemHelper.install_tasks
7
7
  require 'rspec/core/rake_task'
8
8
  RSpec::Core::RakeTask.new(:spec) do |spec|
9
9
  spec.pattern = 'spec/**/*_spec.rb'
10
+ spec.exclude_pattern = 'spec/integration/**/*_spec.rb'
10
11
  end
11
12
 
12
13
  RSpec::Core::RakeTask.new(:rcov) do |spec|
@@ -1,6 +1,95 @@
1
1
  Upgrading Grape
2
2
  ===============
3
3
 
4
+ ### Upgrading to >= 1.0.0
5
+
6
+ #### Changes in XML and JSON Parsers
7
+
8
+ Grape no longer uses `multi_json` or `multi_xml` by default and uses `JSON` and `ActiveSupport::XmlMini` instead. This has no visible impact on JSON processing, but the default behavior of the XML parser has changed. For example, an XML POST containing `<user>Bobby T.</user>` was parsed as `Bobby T.` with `multi_xml`, and as now parsed as `{"__content__"=>"Bobby T."}` with `XmlMini`.
9
+
10
+ If you were using `MultiJson.load`, `MultiJson.dump` or `MultiXml.parse`, you can substitute those with `Grape::Json.load`, `Grape::Json.dump`, `::Grape::Xml.parse`, or directly with `JSON.load`, `JSON.dump`, `XmlMini.parse`, etc.
11
+
12
+ To restore previous behavior, add `multi_json` or `multi_xml` to your `Gemfile` and `require` it.
13
+
14
+ See [#1623](https://github.com/ruby-grape/grape/pull/1623) for more information.
15
+
16
+ #### Changes in Parameter Class
17
+
18
+ The default class for `params` has changed from `Hashie::Mash` to `ActiveSupport::HashWithIndifferentAccess` and the `hashie` dependency has been removed. This means that by default you can no longer access parameters by method name.
19
+
20
+ ```ruby
21
+ class API < Grape::API
22
+ params do
23
+ optional :color, type: String
24
+ end
25
+ get do
26
+ params[:color] # use params[:color] instead of params.color
27
+ end
28
+ end
29
+ ```
30
+
31
+ To restore the behavior of prior versions, add `hashie` to your `Gemfile` and `include Grape::Extensions::Hashie::Mash::ParamBuilder` in your API.
32
+
33
+ ```ruby
34
+ class API < Grape::API
35
+ include Grape::Extensions::Hashie::Mash::ParamBuilder
36
+
37
+ params do
38
+ optional :color, type: String
39
+ end
40
+ get do
41
+ # params.color works
42
+ end
43
+ end
44
+ ```
45
+
46
+ This behavior can also be overridden on individual parameter blocks using `build_with`.
47
+
48
+ ```ruby
49
+ params do
50
+ build_with Grape::Extensions::Hash::ParamBuilder
51
+ optional :color, type: String
52
+ end
53
+ ```
54
+
55
+ If you're constructing your own `Grape::Request` in a middleware, you can pass different parameter handlers to create the desired `params` class with `build_params_with`.
56
+
57
+ ```ruby
58
+ def request
59
+ Grape::Request.new(env, build_params_with: Grape::Extensions::Hashie::Mash::ParamBuilder)
60
+ end
61
+ ```
62
+
63
+ See [#1610](https://github.com/ruby-grape/grape/pull/1610) for more information.
64
+
65
+ #### The `except`, `except_message`, and `proc` options of the `values` validator are deprecated.
66
+
67
+ The new `except_values` validator should be used in place of the `except` and `except_message` options of
68
+ the `values` validator.
69
+
70
+ Arity one Procs may now be used directly as the `values` option to explicitly test param values.
71
+
72
+ **Deprecated**
73
+ ```ruby
74
+ params do
75
+ requires :a, values: { value: 0..99, except: [3] }
76
+ requires :b, values: { value: 0..99, except: [3], except_message: 'not allowed' }
77
+ requires :c, values: { except: ['admin'] }
78
+ requires :d, values: { proc: -> (v) { v.even? } }
79
+ end
80
+ ```
81
+ **New**
82
+ ```ruby
83
+ params do
84
+ requires :a, values: 0..99, except_values: [3]
85
+ requires :b, values: 0..99, except_values: { value: [3], message: 'not allowed' }
86
+ requires :c, except_values: ['admin']
87
+ requires :d, values: -> (v) { v.even? }
88
+ end
89
+ ```
90
+
91
+ See [#1616](https://github.com/ruby-grape/grape/pull/1616) for more information.
92
+
4
93
  ### Upgrading to >= 0.19.1
5
94
 
6
95
  #### DELETE now defaults to status code 200 for responses with a body, or 204 otherwise
@@ -0,0 +1,22 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ require 'grape'
3
+ require 'benchmark/ips'
4
+
5
+ api = Class.new(Grape::API) do
6
+ prefix :api
7
+ version 'v1', using: :path
8
+ params do
9
+ requires :param, type: Array[String]
10
+ end
11
+ get '/' do
12
+ 'hello'
13
+ end
14
+ end
15
+
16
+ env = Rack::MockRequest.env_for('/api/v1?param=value', method: 'GET')
17
+
18
+ Benchmark.ips do |ips|
19
+ ips.report('simple_with_type_coercer') do
20
+ api.call(env)
21
+ end
22
+ end
@@ -0,0 +1,36 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gem 'multi_json', require: 'multi_json'
6
+
7
+ group :development, :test do
8
+ gem 'bundler'
9
+ gem 'rake'
10
+ gem 'rubocop', '0.47.0'
11
+ gem 'hashie'
12
+ end
13
+
14
+ group :development do
15
+ gem 'guard'
16
+ gem 'guard-rspec'
17
+ gem 'guard-rubocop'
18
+ gem 'yard'
19
+ gem 'appraisal'
20
+ gem 'benchmark-ips'
21
+ gem 'redcarpet'
22
+ end
23
+
24
+ group :test do
25
+ gem 'grape-entity', '~> 0.6'
26
+ gem 'maruku'
27
+ gem 'rack-test'
28
+ gem 'rspec', '~> 3.0'
29
+ gem 'cookiejar'
30
+ gem 'rack-jsonp', require: 'rack/jsonp'
31
+ gem 'mime-types'
32
+ gem 'ruby-grape-danger', '~> 0.1.0', require: false
33
+ gem 'coveralls', '~> 0.8.17', require: false
34
+ end
35
+
36
+ gemspec path: '../'
@@ -0,0 +1,36 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gem 'multi_xml', require: 'multi_xml'
6
+
7
+ group :development, :test do
8
+ gem 'bundler'
9
+ gem 'rake'
10
+ gem 'rubocop', '0.47.0'
11
+ gem 'hashie'
12
+ end
13
+
14
+ group :development do
15
+ gem 'guard'
16
+ gem 'guard-rspec'
17
+ gem 'guard-rubocop'
18
+ gem 'yard'
19
+ gem 'appraisal'
20
+ gem 'benchmark-ips'
21
+ gem 'redcarpet'
22
+ end
23
+
24
+ group :test do
25
+ gem 'grape-entity', '~> 0.6'
26
+ gem 'maruku'
27
+ gem 'rack-test'
28
+ gem 'rspec', '~> 3.0'
29
+ gem 'cookiejar'
30
+ gem 'rack-jsonp', require: 'rack/jsonp'
31
+ gem 'mime-types'
32
+ gem 'ruby-grape-danger', '~> 0.1.0', require: false
33
+ gem 'coveralls', '~> 0.8.17', require: false
34
+ end
35
+
36
+ gemspec path: '../'
@@ -8,6 +8,7 @@ group :development, :test do
8
8
  gem 'bundler'
9
9
  gem 'rake'
10
10
  gem 'rubocop', '0.47.0'
11
+ gem 'hashie'
11
12
  end
12
13
 
13
14
  group :development do
@@ -8,6 +8,7 @@ group :development, :test do
8
8
  gem 'bundler'
9
9
  gem 'rake'
10
10
  gem 'rubocop', '0.47.0'
11
+ gem 'hashie'
11
12
  end
12
13
 
13
14
  group :development do
@@ -9,6 +9,7 @@ group :development, :test do
9
9
  gem 'bundler'
10
10
  gem 'rake'
11
11
  gem 'rubocop', '0.47.0'
12
+ gem 'hashie'
12
13
  end
13
14
 
14
15
  group :development do
@@ -8,6 +8,7 @@ group :development, :test do
8
8
  gem 'bundler'
9
9
  gem 'rake'
10
10
  gem 'rubocop', '0.47.0'
11
+ gem 'hashie'
11
12
  end
12
13
 
13
14
  group :development do
@@ -8,6 +8,7 @@ group :development, :test do
8
8
  gem 'bundler'
9
9
  gem 'rake'
10
10
  gem 'rubocop', '0.47.0'
11
+ gem 'hashie'
11
12
  end
12
13
 
13
14
  group :development do
@@ -8,6 +8,7 @@ group :development, :test do
8
8
  gem 'bundler'
9
9
  gem 'rake'
10
10
  gem 'rubocop', '0.47.0'
11
+ gem 'hashie'
11
12
  end
12
13
 
13
14
  group :development do
@@ -16,9 +16,6 @@ Gem::Specification.new do |s|
16
16
  s.add_runtime_dependency 'mustermann-grape', '~> 1.0.0'
17
17
  s.add_runtime_dependency 'rack-accept'
18
18
  s.add_runtime_dependency 'activesupport'
19
- s.add_runtime_dependency 'multi_json', '>= 1.3.2'
20
- s.add_runtime_dependency 'multi_xml', '>= 0.5.2'
21
- s.add_runtime_dependency 'hashie', '>= 2.1.0'
22
19
  s.add_runtime_dependency 'virtus', '>= 1.0.0'
23
20
  s.add_runtime_dependency 'builder'
24
21
 
@@ -4,7 +4,6 @@ require 'rack/builder'
4
4
  require 'rack/accept'
5
5
  require 'rack/auth/basic'
6
6
  require 'rack/auth/digest/md5'
7
- require 'hashie'
8
7
  require 'set'
9
8
  require 'active_support/version'
10
9
  require 'active_support/core_ext/hash/indifferent_access'
@@ -17,8 +16,6 @@ require 'active_support/core_ext/hash/except'
17
16
  require 'active_support/core_ext/hash/conversions'
18
17
  require 'active_support/dependencies/autoload'
19
18
  require 'active_support/notifications'
20
- require 'multi_json'
21
- require 'multi_xml'
22
19
  require 'i18n'
23
20
  require 'thread'
24
21
 
@@ -27,7 +24,7 @@ require 'virtus'
27
24
  I18n.load_path << File.expand_path('../grape/locale/en.yml', __FILE__)
28
25
 
29
26
  module Grape
30
- extend ActiveSupport::Autoload
27
+ extend ::ActiveSupport::Autoload
31
28
 
32
29
  eager_autoload do
33
30
  autoload :API
@@ -45,17 +42,19 @@ module Grape
45
42
  autoload :Parser
46
43
  autoload :Request
47
44
  autoload :Env, 'grape/util/env'
45
+ autoload :Json, 'grape/util/json'
46
+ autoload :Xml, 'grape/util/xml'
48
47
  end
49
48
 
50
49
  module Http
51
- extend ActiveSupport::Autoload
50
+ extend ::ActiveSupport::Autoload
52
51
  eager_autoload do
53
52
  autoload :Headers
54
53
  end
55
54
  end
56
55
 
57
56
  module Exceptions
58
- extend ActiveSupport::Autoload
57
+ extend ::ActiveSupport::Autoload
59
58
  autoload :Base
60
59
  autoload :Validation
61
60
  autoload :ValidationArrayErrors
@@ -78,16 +77,38 @@ module Grape
78
77
  autoload :MethodNotAllowed
79
78
  end
80
79
 
80
+ module Extensions
81
+ extend ::ActiveSupport::Autoload
82
+
83
+ autoload :DeepMergeableHash
84
+ autoload :DeepSymbolizeHash
85
+ autoload :DeepHashWithIndifferentAccess
86
+ autoload :Hash
87
+
88
+ module ActiveSupport
89
+ extend ::ActiveSupport::Autoload
90
+
91
+ autoload :HashWithIndifferentAccess
92
+ end
93
+
94
+ module Hashie
95
+ extend ::ActiveSupport::Autoload
96
+
97
+ autoload :Mash
98
+ end
99
+ end
100
+
81
101
  module Middleware
82
- extend ActiveSupport::Autoload
102
+ extend ::ActiveSupport::Autoload
83
103
  autoload :Base
84
104
  autoload :Versioner
85
105
  autoload :Formatter
86
106
  autoload :Error
87
107
  autoload :Globals
108
+ autoload :Stack
88
109
 
89
110
  module Auth
90
- extend ActiveSupport::Autoload
111
+ extend ::ActiveSupport::Autoload
91
112
  autoload :Base
92
113
  autoload :DSL
93
114
  autoload :StrategyInfo
@@ -95,7 +116,7 @@ module Grape
95
116
  end
96
117
 
97
118
  module Versioner
98
- extend ActiveSupport::Autoload
119
+ extend ::ActiveSupport::Autoload
99
120
  autoload :Path
100
121
  autoload :Header
101
122
  autoload :Param
@@ -104,7 +125,7 @@ module Grape
104
125
  end
105
126
 
106
127
  module Util
107
- extend ActiveSupport::Autoload
128
+ extend ::ActiveSupport::Autoload
108
129
  autoload :InheritableValues
109
130
  autoload :StackableValues
110
131
  autoload :ReverseStackableValues
@@ -114,7 +135,7 @@ module Grape
114
135
  end
115
136
 
116
137
  module ErrorFormatter
117
- extend ActiveSupport::Autoload
138
+ extend ::ActiveSupport::Autoload
118
139
  autoload :Base
119
140
  autoload :Json
120
141
  autoload :Txt
@@ -122,7 +143,7 @@ module Grape
122
143
  end
123
144
 
124
145
  module Formatter
125
- extend ActiveSupport::Autoload
146
+ extend ::ActiveSupport::Autoload
126
147
  autoload :Json
127
148
  autoload :SerializableHash
128
149
  autoload :Txt
@@ -130,13 +151,13 @@ module Grape
130
151
  end
131
152
 
132
153
  module Parser
133
- extend ActiveSupport::Autoload
154
+ extend ::ActiveSupport::Autoload
134
155
  autoload :Json
135
156
  autoload :Xml
136
157
  end
137
158
 
138
159
  module DSL
139
- extend ActiveSupport::Autoload
160
+ extend ::ActiveSupport::Autoload
140
161
  eager_autoload do
141
162
  autoload :API
142
163
  autoload :Callbacks
@@ -155,17 +176,17 @@ module Grape
155
176
  end
156
177
 
157
178
  class API
158
- extend ActiveSupport::Autoload
179
+ extend ::ActiveSupport::Autoload
159
180
  autoload :Helpers
160
181
  end
161
182
 
162
183
  module Presenters
163
- extend ActiveSupport::Autoload
184
+ extend ::ActiveSupport::Autoload
164
185
  autoload :Presenter
165
186
  end
166
187
 
167
188
  module ServeFile
168
- extend ActiveSupport::Autoload
189
+ extend ::ActiveSupport::Autoload
169
190
  autoload :FileResponse
170
191
  autoload :FileBody
171
192
  autoload :SendfileResponse
@@ -185,8 +206,10 @@ require 'grape/validations/validators/mutual_exclusion'
185
206
  require 'grape/validations/validators/presence'
186
207
  require 'grape/validations/validators/regexp'
187
208
  require 'grape/validations/validators/values'
209
+ require 'grape/validations/validators/except_values'
188
210
  require 'grape/validations/params_scope'
189
211
  require 'grape/validations/validators/all_or_none'
190
212
  require 'grape/validations/types'
213
+ require 'grape/validations/validator_factory'
191
214
 
192
215
  require 'grape/version'
@@ -13,7 +13,7 @@ module Grape
13
13
  # When called without a block, all known helpers within this scope
14
14
  # are included.
15
15
  #
16
- # @param [Module] new_mod optional module of methods to include
16
+ # @param [Array] new_modules optional array of modules to include
17
17
  # @param [Block] block optional block of methods to include
18
18
  #
19
19
  # @example Define some helpers.
@@ -26,28 +26,42 @@ module Grape
26
26
  # end
27
27
  # end
28
28
  #
29
- def helpers(new_mod = nil, &block)
30
- if block_given? || new_mod
31
- mod = new_mod || Module.new
32
- define_boolean_in_mod(mod)
33
- inject_api_helpers_to_mod(mod) if new_mod
29
+ # @example Include many modules
30
+ #
31
+ # class ExampleAPI < Grape::API
32
+ # helpers Authentication, Mailer, OtherModule
33
+ # end
34
+ #
35
+ def helpers(*new_modules, &block)
36
+ include_new_modules(new_modules) if new_modules.any?
37
+ include_block(block) if block_given?
38
+ include_all_in_scope if !block_given? && new_modules.empty?
39
+ end
34
40
 
35
- inject_api_helpers_to_mod(mod) do
36
- mod.class_eval(&block)
37
- end if block_given?
41
+ protected
38
42
 
39
- namespace_stackable(:helpers, mod)
40
- else
41
- mod = Module.new
42
- namespace_stackable(:helpers).each do |mod_to_include|
43
- mod.send :include, mod_to_include
44
- end
45
- change!
46
- mod
43
+ def include_new_modules(modules)
44
+ modules.each { |mod| make_inclusion(mod) }
45
+ end
46
+
47
+ def include_block(block)
48
+ Module.new.tap do |mod|
49
+ make_inclusion(mod) { mod.class_eval(&block) }
47
50
  end
48
51
  end
49
52
 
50
- protected
53
+ def make_inclusion(mod, &block)
54
+ define_boolean_in_mod(mod)
55
+ inject_api_helpers_to_mod(mod, &block)
56
+ namespace_stackable(:helpers, mod)
57
+ end
58
+
59
+ def include_all_in_scope
60
+ Module.new.tap do |mod|
61
+ namespace_stackable(:helpers).each { |mod_to_include| mod.send :include, mod_to_include }
62
+ change!
63
+ end
64
+ end
51
65
 
52
66
  def define_boolean_in_mod(mod)
53
67
  return if defined? mod::Boolean