grape 1.5.2 → 1.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +47 -0
  3. data/CONTRIBUTING.md +2 -1
  4. data/README.md +33 -3
  5. data/UPGRADING.md +71 -2
  6. data/grape.gemspec +5 -5
  7. data/lib/grape/api/instance.rb +13 -17
  8. data/lib/grape/api.rb +18 -13
  9. data/lib/grape/cookies.rb +2 -0
  10. data/lib/grape/dsl/desc.rb +3 -5
  11. data/lib/grape/dsl/headers.rb +5 -2
  12. data/lib/grape/dsl/helpers.rb +7 -5
  13. data/lib/grape/dsl/inside_route.rb +17 -8
  14. data/lib/grape/dsl/middleware.rb +4 -4
  15. data/lib/grape/dsl/parameters.rb +3 -3
  16. data/lib/grape/dsl/request_response.rb +9 -6
  17. data/lib/grape/dsl/routing.rb +2 -2
  18. data/lib/grape/dsl/settings.rb +5 -5
  19. data/lib/grape/endpoint.rb +21 -36
  20. data/lib/grape/error_formatter/json.rb +2 -6
  21. data/lib/grape/error_formatter/xml.rb +2 -6
  22. data/lib/grape/exceptions/empty_message_body.rb +11 -0
  23. data/lib/grape/exceptions/validation.rb +1 -2
  24. data/lib/grape/formatter/json.rb +1 -0
  25. data/lib/grape/formatter/serializable_hash.rb +2 -1
  26. data/lib/grape/formatter/xml.rb +1 -0
  27. data/lib/grape/locale/en.yml +1 -1
  28. data/lib/grape/middleware/auth/dsl.rb +7 -1
  29. data/lib/grape/middleware/base.rb +3 -1
  30. data/lib/grape/middleware/formatter.rb +4 -4
  31. data/lib/grape/middleware/stack.rb +2 -2
  32. data/lib/grape/middleware/versioner/accept_version_header.rb +3 -5
  33. data/lib/grape/middleware/versioner/header.rb +6 -4
  34. data/lib/grape/middleware/versioner/param.rb +1 -0
  35. data/lib/grape/middleware/versioner/parse_media_type_patch.rb +2 -1
  36. data/lib/grape/middleware/versioner/path.rb +2 -0
  37. data/lib/grape/parser/json.rb +1 -1
  38. data/lib/grape/parser/xml.rb +1 -1
  39. data/lib/grape/path.rb +1 -0
  40. data/lib/grape/request.rb +3 -0
  41. data/lib/grape/router/pattern.rb +1 -1
  42. data/lib/grape/router/route.rb +2 -2
  43. data/lib/grape/router.rb +6 -0
  44. data/lib/grape/util/inheritable_setting.rb +1 -3
  45. data/lib/grape/util/lazy_value.rb +3 -2
  46. data/lib/grape/util/strict_hash_configuration.rb +1 -1
  47. data/lib/grape/validations/params_scope.rb +88 -55
  48. data/lib/grape/validations/types/custom_type_coercer.rb +1 -2
  49. data/lib/grape/validations/types/dry_type_coercer.rb +1 -1
  50. data/lib/grape/validations/types/json.rb +2 -1
  51. data/lib/grape/validations/types/primitive_coercer.rb +3 -3
  52. data/lib/grape/validations/validators/all_or_none.rb +8 -5
  53. data/lib/grape/validations/validators/allow_blank.rb +9 -7
  54. data/lib/grape/validations/validators/as.rb +6 -8
  55. data/lib/grape/validations/validators/at_least_one_of.rb +7 -4
  56. data/lib/grape/validations/validators/base.rb +75 -70
  57. data/lib/grape/validations/validators/coerce.rb +63 -79
  58. data/lib/grape/validations/validators/default.rb +37 -34
  59. data/lib/grape/validations/validators/exactly_one_of.rb +9 -6
  60. data/lib/grape/validations/validators/except_values.rb +13 -11
  61. data/lib/grape/validations/validators/multiple_params_base.rb +24 -20
  62. data/lib/grape/validations/validators/mutual_exclusion.rb +8 -5
  63. data/lib/grape/validations/validators/presence.rb +7 -4
  64. data/lib/grape/validations/validators/regexp.rb +8 -5
  65. data/lib/grape/validations/validators/same_as.rb +18 -15
  66. data/lib/grape/validations/validators/values.rb +61 -56
  67. data/lib/grape/validations.rb +6 -0
  68. data/lib/grape/version.rb +1 -1
  69. data/lib/grape.rb +4 -1
  70. data/spec/grape/api/custom_validations_spec.rb +77 -45
  71. data/spec/grape/api/deeply_included_options_spec.rb +3 -3
  72. data/spec/grape/api/defines_boolean_in_params_spec.rb +2 -1
  73. data/spec/grape/api/invalid_format_spec.rb +2 -0
  74. data/spec/grape/api/recognize_path_spec.rb +1 -1
  75. data/spec/grape/api/routes_with_requirements_spec.rb +8 -8
  76. data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +9 -15
  77. data/spec/grape/api_remount_spec.rb +16 -15
  78. data/spec/grape/api_spec.rb +510 -220
  79. data/spec/grape/dsl/callbacks_spec.rb +2 -1
  80. data/spec/grape/dsl/headers_spec.rb +39 -9
  81. data/spec/grape/dsl/helpers_spec.rb +3 -2
  82. data/spec/grape/dsl/inside_route_spec.rb +6 -4
  83. data/spec/grape/dsl/logger_spec.rb +16 -18
  84. data/spec/grape/dsl/middleware_spec.rb +2 -1
  85. data/spec/grape/dsl/parameters_spec.rb +2 -0
  86. data/spec/grape/dsl/request_response_spec.rb +1 -0
  87. data/spec/grape/dsl/routing_spec.rb +10 -7
  88. data/spec/grape/endpoint/declared_spec.rb +259 -12
  89. data/spec/grape/endpoint_spec.rb +77 -55
  90. data/spec/grape/entity_spec.rb +22 -22
  91. data/spec/grape/exceptions/body_parse_errors_spec.rb +3 -0
  92. data/spec/grape/exceptions/invalid_accept_header_spec.rb +61 -22
  93. data/spec/grape/exceptions/validation_errors_spec.rb +13 -10
  94. data/spec/grape/exceptions/validation_spec.rb +5 -3
  95. data/spec/grape/extensions/param_builders/hash_spec.rb +7 -7
  96. data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +8 -8
  97. data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +8 -8
  98. data/spec/grape/integration/rack_sendfile_spec.rb +1 -1
  99. data/spec/grape/loading_spec.rb +8 -8
  100. data/spec/grape/middleware/auth/dsl_spec.rb +15 -6
  101. data/spec/grape/middleware/auth/strategies_spec.rb +60 -20
  102. data/spec/grape/middleware/base_spec.rb +24 -15
  103. data/spec/grape/middleware/error_spec.rb +2 -2
  104. data/spec/grape/middleware/exception_spec.rb +111 -161
  105. data/spec/grape/middleware/formatter_spec.rb +27 -6
  106. data/spec/grape/middleware/globals_spec.rb +7 -4
  107. data/spec/grape/middleware/stack_spec.rb +14 -12
  108. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +2 -1
  109. data/spec/grape/middleware/versioner/header_spec.rb +14 -13
  110. data/spec/grape/middleware/versioner/param_spec.rb +7 -1
  111. data/spec/grape/middleware/versioner/path_spec.rb +5 -1
  112. data/spec/grape/middleware/versioner_spec.rb +1 -1
  113. data/spec/grape/parser_spec.rb +4 -0
  114. data/spec/grape/path_spec.rb +52 -52
  115. data/spec/grape/presenters/presenter_spec.rb +7 -6
  116. data/spec/grape/request_spec.rb +6 -4
  117. data/spec/grape/util/inheritable_setting_spec.rb +7 -7
  118. data/spec/grape/util/inheritable_values_spec.rb +3 -2
  119. data/spec/grape/util/reverse_stackable_values_spec.rb +3 -1
  120. data/spec/grape/util/stackable_values_spec.rb +7 -5
  121. data/spec/grape/validations/instance_behaivour_spec.rb +9 -10
  122. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +1 -0
  123. data/spec/grape/validations/params_scope_spec.rb +46 -10
  124. data/spec/grape/validations/single_attribute_iterator_spec.rb +2 -1
  125. data/spec/grape/validations/types/primitive_coercer_spec.rb +4 -4
  126. data/spec/grape/validations/types_spec.rb +8 -8
  127. data/spec/grape/validations/validators/all_or_none_spec.rb +50 -56
  128. data/spec/grape/validations/validators/allow_blank_spec.rb +136 -140
  129. data/spec/grape/validations/validators/at_least_one_of_spec.rb +50 -56
  130. data/spec/grape/validations/validators/coerce_spec.rb +99 -22
  131. data/spec/grape/validations/validators/default_spec.rb +72 -78
  132. data/spec/grape/validations/validators/exactly_one_of_spec.rb +71 -77
  133. data/spec/grape/validations/validators/except_values_spec.rb +3 -3
  134. data/spec/grape/validations/validators/mutual_exclusion_spec.rb +71 -77
  135. data/spec/grape/validations/validators/presence_spec.rb +16 -1
  136. data/spec/grape/validations/validators/regexp_spec.rb +25 -31
  137. data/spec/grape/validations/validators/same_as_spec.rb +14 -20
  138. data/spec/grape/validations/validators/values_spec.rb +183 -178
  139. data/spec/grape/validations_spec.rb +99 -58
  140. data/spec/integration/eager_load/eager_load_spec.rb +2 -2
  141. data/spec/integration/multi_json/json_spec.rb +1 -1
  142. data/spec/integration/multi_xml/xml_spec.rb +1 -1
  143. data/spec/shared/versioning_examples.rb +12 -9
  144. data/spec/spec_helper.rb +12 -2
  145. data/spec/support/basic_auth_encode_helpers.rb +1 -1
  146. metadata +102 -101
@@ -10,32 +10,32 @@ describe Grape::Endpoint do
10
10
  end
11
11
 
12
12
  describe '.before_each' do
13
- after { Grape::Endpoint.before_each.clear }
13
+ after { described_class.before_each.clear }
14
14
 
15
15
  it 'is settable via block' do
16
16
  block = ->(_endpoint) { 'noop' }
17
- Grape::Endpoint.before_each(&block)
18
- expect(Grape::Endpoint.before_each.first).to eq(block)
17
+ described_class.before_each(&block)
18
+ expect(described_class.before_each.first).to eq(block)
19
19
  end
20
20
 
21
21
  it 'is settable via reference' do
22
22
  block = ->(_endpoint) { 'noop' }
23
- Grape::Endpoint.before_each block
24
- expect(Grape::Endpoint.before_each.first).to eq(block)
23
+ described_class.before_each block
24
+ expect(described_class.before_each.first).to eq(block)
25
25
  end
26
26
 
27
27
  it 'is able to override a helper' do
28
28
  subject.get('/') { current_user }
29
29
  expect { get '/' }.to raise_error(NameError)
30
30
 
31
- Grape::Endpoint.before_each do |endpoint|
31
+ described_class.before_each do |endpoint|
32
32
  allow(endpoint).to receive(:current_user).and_return('Bob')
33
33
  end
34
34
 
35
35
  get '/'
36
36
  expect(last_response.body).to eq('Bob')
37
37
 
38
- Grape::Endpoint.before_each(nil)
38
+ described_class.before_each(nil)
39
39
  expect { get '/' }.to raise_error(NameError)
40
40
  end
41
41
 
@@ -46,18 +46,18 @@ describe Grape::Endpoint do
46
46
  end
47
47
  expect { get '/' }.to raise_error(NameError)
48
48
 
49
- Grape::Endpoint.before_each do |endpoint|
49
+ described_class.before_each do |endpoint|
50
50
  allow(endpoint).to receive(:current_user).and_return('Bob')
51
51
  end
52
52
 
53
- Grape::Endpoint.before_each do |endpoint|
53
+ described_class.before_each do |endpoint|
54
54
  allow(endpoint).to receive(:authenticate_user!).and_return(true)
55
55
  end
56
56
 
57
57
  get '/'
58
58
  expect(last_response.body).to eq('Bob')
59
59
 
60
- Grape::Endpoint.before_each(nil)
60
+ described_class.before_each(nil)
61
61
  expect { get '/' }.to raise_error(NameError)
62
62
  end
63
63
  end
@@ -66,7 +66,7 @@ describe Grape::Endpoint do
66
66
  it 'takes a settings stack, options, and a block' do
67
67
  p = proc {}
68
68
  expect do
69
- Grape::Endpoint.new(Grape::Util::InheritableSetting.new, {
69
+ described_class.new(Grape::Util::InheritableSetting.new, {
70
70
  path: '/',
71
71
  method: :get
72
72
  }, &p)
@@ -77,7 +77,7 @@ describe Grape::Endpoint do
77
77
  it 'sets itself in the env upon call' do
78
78
  subject.get('/') { 'Hello world.' }
79
79
  get '/'
80
- expect(last_request.env['api.endpoint']).to be_kind_of(Grape::Endpoint)
80
+ expect(last_request.env['api.endpoint']).to be_kind_of(described_class)
81
81
  end
82
82
 
83
83
  describe '#status' do
@@ -137,6 +137,7 @@ describe Grape::Endpoint do
137
137
  headers.to_json
138
138
  end
139
139
  end
140
+
140
141
  it 'includes request headers' do
141
142
  get '/headers'
142
143
  expect(JSON.parse(last_response.body)).to eq(
@@ -144,13 +145,15 @@ describe Grape::Endpoint do
144
145
  'Cookie' => ''
145
146
  )
146
147
  end
148
+
147
149
  it 'includes additional request headers' do
148
150
  get '/headers', nil, 'HTTP_X_GRAPE_CLIENT' => '1'
149
151
  expect(JSON.parse(last_response.body)['X-Grape-Client']).to eq('1')
150
152
  end
153
+
151
154
  it 'includes headers passed as symbols' do
152
155
  env = Rack::MockRequest.env_for('/headers')
153
- env['HTTP_SYMBOL_HEADER'.to_sym] = 'Goliath passes symbols'
156
+ env[:HTTP_SYMBOL_HEADER] = 'Goliath passes symbols'
154
157
  body = read_chunks(subject.call(env)[2]).join
155
158
  expect(JSON.parse(body)['Symbol-Header']).to eq('Goliath passes symbols')
156
159
  end
@@ -212,10 +215,10 @@ describe Grape::Endpoint do
212
215
  end
213
216
  get '/test', {}, 'HTTP_COOKIE' => 'delete_this_cookie=1; and_this=2'
214
217
  expect(last_response.body).to eq('3')
215
- cookies = Hash[last_response.headers['Set-Cookie'].split("\n").map do |set_cookie|
218
+ cookies = last_response.headers['Set-Cookie'].split("\n").map do |set_cookie|
216
219
  cookie = CookieJar::Cookie.from_set_cookie 'http://localhost/test', set_cookie
217
220
  [cookie.name, cookie]
218
- end]
221
+ end.to_h
219
222
  expect(cookies.size).to eq(2)
220
223
  %w[and_this delete_this_cookie].each do |cookie_name|
221
224
  cookie = cookies[cookie_name]
@@ -236,10 +239,10 @@ describe Grape::Endpoint do
236
239
  end
237
240
  get('/test', {}, 'HTTP_COOKIE' => 'delete_this_cookie=1; and_this=2')
238
241
  expect(last_response.body).to eq('3')
239
- cookies = Hash[last_response.headers['Set-Cookie'].split("\n").map do |set_cookie|
242
+ cookies = last_response.headers['Set-Cookie'].split("\n").map do |set_cookie|
240
243
  cookie = CookieJar::Cookie.from_set_cookie 'http://localhost/test', set_cookie
241
244
  [cookie.name, cookie]
242
- end]
245
+ end.to_h
243
246
  expect(cookies.size).to eq(2)
244
247
  %w[and_this delete_this_cookie].each do |cookie_name|
245
248
  cookie = cookies[cookie_name]
@@ -253,7 +256,7 @@ describe Grape::Endpoint do
253
256
 
254
257
  describe '#params' do
255
258
  context 'default class' do
256
- it 'should be a ActiveSupport::HashWithIndifferentAccess' do
259
+ it 'is a ActiveSupport::HashWithIndifferentAccess' do
257
260
  subject.get '/foo' do
258
261
  params.class
259
262
  end
@@ -339,7 +342,7 @@ describe Grape::Endpoint do
339
342
  end
340
343
 
341
344
  context 'namespace requirements' do
342
- before :each do
345
+ before do
343
346
  subject.namespace :outer, requirements: { person_email: /abc@(.*).com/ } do
344
347
  get('/:person_email') do
345
348
  params[:person_email]
@@ -358,7 +361,7 @@ describe Grape::Endpoint do
358
361
  expect(last_response.body).to eq('abc@example.com')
359
362
  end
360
363
 
361
- it "should override outer namespace's requirements" do
364
+ it "overrides outer namespace's requirements" do
362
365
  get '/outer/inner/someone@testing.wrong/test/1'
363
366
  expect(last_response.status).to eq(404)
364
367
 
@@ -370,7 +373,7 @@ describe Grape::Endpoint do
370
373
  end
371
374
 
372
375
  context 'from body parameters' do
373
- before(:each) do
376
+ before do
374
377
  subject.post '/request_body' do
375
378
  params[:user]
376
379
  end
@@ -420,6 +423,19 @@ describe Grape::Endpoint do
420
423
  expect(last_response.status).to eq(201)
421
424
  expect(last_response.body).to eq('Bob')
422
425
  end
426
+
427
+ # Rack swallowed this error until v2.2.0
428
+ it 'returns a 400 if given an invalid multipart body', if: Gem::Version.new(Rack.release) >= Gem::Version.new('2.2.0') do
429
+ subject.params do
430
+ requires :file, type: Rack::Multipart::UploadedFile
431
+ end
432
+ subject.post '/upload' do
433
+ params[:file][:filename]
434
+ end
435
+ post '/upload', { file: '' }, 'CONTENT_TYPE' => 'multipart/form-data; boundary=foobar'
436
+ expect(last_response.status).to eq(400)
437
+ expect(last_response.body).to eq('Empty message body supplied with multipart/form-data; boundary=foobar content-type')
438
+ end
423
439
  end
424
440
 
425
441
  it 'responds with a 415 for an unsupported content-type' do
@@ -456,11 +472,11 @@ describe Grape::Endpoint do
456
472
  post '/', ::Grape::Json.dump(data: { some: 'payload' }), 'CONTENT_TYPE' => 'application/json'
457
473
  end
458
474
 
459
- it 'should not response with 406 for same type without params' do
475
+ it 'does not response with 406 for same type without params' do
460
476
  expect(last_response.status).not_to be 406
461
477
  end
462
478
 
463
- it 'should response with given content type in headers' do
479
+ it 'responses with given content type in headers' do
464
480
  expect(last_response.headers['Content-Type']).to eq 'application/json; charset=utf-8'
465
481
  end
466
482
  end
@@ -696,16 +712,18 @@ describe Grape::Endpoint do
696
712
  describe '.generate_api_method' do
697
713
  it 'raises NameError if the method name is already in use' do
698
714
  expect do
699
- Grape::Endpoint.generate_api_method('version', &proc {})
715
+ described_class.generate_api_method('version', &proc {})
700
716
  end.to raise_error(NameError)
701
717
  end
718
+
702
719
  it 'raises ArgumentError if a block is not given' do
703
720
  expect do
704
- Grape::Endpoint.generate_api_method('GET without a block method')
721
+ described_class.generate_api_method('GET without a block method')
705
722
  end.to raise_error(ArgumentError)
706
723
  end
724
+
707
725
  it 'returns a Proc' do
708
- expect(Grape::Endpoint.generate_api_method('GET test for a proc', &proc {})).to be_a Proc
726
+ expect(described_class.generate_api_method('GET test for a proc', &proc {})).to be_a Proc
709
727
  end
710
728
  end
711
729
 
@@ -764,7 +782,7 @@ describe Grape::Endpoint do
764
782
  end
765
783
 
766
784
  get '/error_filters'
767
- expect(last_response.status).to eql 500
785
+ expect(last_response.status).to be 500
768
786
  expect(called).to match_array %w[before before_validation]
769
787
  end
770
788
 
@@ -773,8 +791,11 @@ describe Grape::Endpoint do
773
791
  subject.before { called << 'parent' }
774
792
  subject.namespace :parent do
775
793
  before { called << 'prior' }
794
+
776
795
  before { error! :oops, 500 }
796
+
777
797
  before { called << 'subsequent' }
798
+
778
799
  get :hello do
779
800
  called << :endpoint
780
801
  'Hello!'
@@ -782,7 +803,7 @@ describe Grape::Endpoint do
782
803
  end
783
804
 
784
805
  get '/parent/hello'
785
- expect(last_response.status).to eql 500
806
+ expect(last_response.status).to be 500
786
807
  expect(called).to match_array %w[parent prior]
787
808
  end
788
809
  end
@@ -793,19 +814,19 @@ describe Grape::Endpoint do
793
814
  it 'allows for the anchoring option with a delete method' do
794
815
  subject.send(:delete, '/example', anchor: true) {}
795
816
  send(:delete, '/example/and/some/more')
796
- expect(last_response.status).to eql 404
817
+ expect(last_response.status).to be 404
797
818
  end
798
819
 
799
820
  it 'anchors paths by default for the delete method' do
800
821
  subject.send(:delete, '/example') {}
801
822
  send(:delete, '/example/and/some/more')
802
- expect(last_response.status).to eql 404
823
+ expect(last_response.status).to be 404
803
824
  end
804
825
 
805
826
  it 'responds to /example/and/some/more for the non-anchored delete method' do
806
827
  subject.send(:delete, '/example', anchor: false) {}
807
828
  send(:delete, '/example/and/some/more')
808
- expect(last_response.status).to eql 204
829
+ expect(last_response.status).to be 204
809
830
  expect(last_response.body).to be_empty
810
831
  end
811
832
  end
@@ -817,7 +838,7 @@ describe Grape::Endpoint do
817
838
  body 'deleted'
818
839
  end
819
840
  send(:delete, '/example/and/some/more')
820
- expect(last_response.status).to eql 200
841
+ expect(last_response.status).to be 200
821
842
  expect(last_response.body).not_to be_empty
822
843
  end
823
844
  end
@@ -826,7 +847,7 @@ describe Grape::Endpoint do
826
847
  it 'responds to /example delete method' do
827
848
  subject.delete(:example) { 'deleted' }
828
849
  delete '/example'
829
- expect(last_response.status).to eql 200
850
+ expect(last_response.status).to be 200
830
851
  expect(last_response.body).not_to be_empty
831
852
  end
832
853
  end
@@ -835,7 +856,7 @@ describe Grape::Endpoint do
835
856
  it 'responds to /example delete method' do
836
857
  subject.delete(:example) { nil }
837
858
  delete '/example'
838
- expect(last_response.status).to eql 204
859
+ expect(last_response.status).to be 204
839
860
  expect(last_response.body).to be_empty
840
861
  end
841
862
  end
@@ -844,7 +865,7 @@ describe Grape::Endpoint do
844
865
  it 'responds to /example delete method' do
845
866
  subject.delete(:example) { '' }
846
867
  delete '/example'
847
- expect(last_response.status).to eql 204
868
+ expect(last_response.status).to be 204
848
869
  expect(last_response.body).to be_empty
849
870
  end
850
871
  end
@@ -856,7 +877,7 @@ describe Grape::Endpoint do
856
877
  verb
857
878
  end
858
879
  send(verb, '/example/and/some/more')
859
- expect(last_response.status).to eql 404
880
+ expect(last_response.status).to be 404
860
881
  end
861
882
 
862
883
  it "anchors paths by default for the #{verb.upcase} method" do
@@ -864,7 +885,7 @@ describe Grape::Endpoint do
864
885
  verb
865
886
  end
866
887
  send(verb, '/example/and/some/more')
867
- expect(last_response.status).to eql 404
888
+ expect(last_response.status).to be 404
868
889
  end
869
890
 
870
891
  it "responds to /example/and/some/more for the non-anchored #{verb.upcase} method" do
@@ -887,8 +908,9 @@ describe Grape::Endpoint do
887
908
  get '/url'
888
909
  expect(last_response.body).to eq('http://example.org/url')
889
910
  end
911
+
890
912
  ['v1', :v1].each do |version|
891
- it "should include version #{version}" do
913
+ it "includes version #{version}" do
892
914
  subject.version version, using: :path
893
915
  subject.get('/url') do
894
916
  request.url
@@ -897,7 +919,7 @@ describe Grape::Endpoint do
897
919
  expect(last_response.body).to eq("http://example.org/#{version}/url")
898
920
  end
899
921
  end
900
- it 'should include prefix' do
922
+ it 'includes prefix' do
901
923
  subject.version 'v1', using: :path
902
924
  subject.prefix 'api'
903
925
  subject.get('/url') do
@@ -987,26 +1009,26 @@ describe Grape::Endpoint do
987
1009
 
988
1010
  # In order that the events finalized (time each block ended)
989
1011
  expect(@events).to contain_exactly(
990
- have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1012
+ have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(described_class),
991
1013
  filters: a_collection_containing_exactly(an_instance_of(Proc)),
992
1014
  type: :before }),
993
- have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1015
+ have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(described_class),
994
1016
  filters: [],
995
1017
  type: :before_validation }),
996
- have_attributes(name: 'endpoint_run_validators.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1018
+ have_attributes(name: 'endpoint_run_validators.grape', payload: { endpoint: a_kind_of(described_class),
997
1019
  validators: [],
998
1020
  request: a_kind_of(Grape::Request) }),
999
- have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1021
+ have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(described_class),
1000
1022
  filters: [],
1001
1023
  type: :after_validation }),
1002
- have_attributes(name: 'endpoint_render.grape', payload: { endpoint: a_kind_of(Grape::Endpoint) }),
1003
- have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1024
+ have_attributes(name: 'endpoint_render.grape', payload: { endpoint: a_kind_of(described_class) }),
1025
+ have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(described_class),
1004
1026
  filters: [],
1005
1027
  type: :after }),
1006
- have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1028
+ have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(described_class),
1007
1029
  filters: [],
1008
1030
  type: :finally }),
1009
- have_attributes(name: 'endpoint_run.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1031
+ have_attributes(name: 'endpoint_run.grape', payload: { endpoint: a_kind_of(described_class),
1010
1032
  env: an_instance_of(Hash) }),
1011
1033
  have_attributes(name: 'format_response.grape', payload: { env: an_instance_of(Hash),
1012
1034
  formatter: a_kind_of(Module) })
@@ -1014,25 +1036,25 @@ describe Grape::Endpoint do
1014
1036
 
1015
1037
  # In order that events were initialized
1016
1038
  expect(@events.sort_by(&:time)).to contain_exactly(
1017
- have_attributes(name: 'endpoint_run.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1039
+ have_attributes(name: 'endpoint_run.grape', payload: { endpoint: a_kind_of(described_class),
1018
1040
  env: an_instance_of(Hash) }),
1019
- have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1041
+ have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(described_class),
1020
1042
  filters: a_collection_containing_exactly(an_instance_of(Proc)),
1021
1043
  type: :before }),
1022
- have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1044
+ have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(described_class),
1023
1045
  filters: [],
1024
1046
  type: :before_validation }),
1025
- have_attributes(name: 'endpoint_run_validators.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1047
+ have_attributes(name: 'endpoint_run_validators.grape', payload: { endpoint: a_kind_of(described_class),
1026
1048
  validators: [],
1027
1049
  request: a_kind_of(Grape::Request) }),
1028
- have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1050
+ have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(described_class),
1029
1051
  filters: [],
1030
1052
  type: :after_validation }),
1031
- have_attributes(name: 'endpoint_render.grape', payload: { endpoint: a_kind_of(Grape::Endpoint) }),
1032
- have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1053
+ have_attributes(name: 'endpoint_render.grape', payload: { endpoint: a_kind_of(described_class) }),
1054
+ have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(described_class),
1033
1055
  filters: [],
1034
1056
  type: :after }),
1035
- have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1057
+ have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(described_class),
1036
1058
  filters: [],
1037
1059
  type: :finally }),
1038
1060
  have_attributes(name: 'format_response.grape', payload: { env: an_instance_of(Hash),
@@ -32,7 +32,7 @@ describe Grape::Entity do
32
32
  end
33
33
 
34
34
  it 'pulls a representation from the class options if it exists' do
35
- entity = Class.new(Grape::Entity)
35
+ entity = Class.new(described_class)
36
36
  allow(entity).to receive(:represent).and_return('Hiya')
37
37
 
38
38
  subject.represent Object, with: entity
@@ -44,7 +44,7 @@ describe Grape::Entity do
44
44
  end
45
45
 
46
46
  it 'pulls a representation from the class options if the presented object is a collection of objects' do
47
- entity = Class.new(Grape::Entity)
47
+ entity = Class.new(described_class)
48
48
  allow(entity).to receive(:represent).and_return('Hiya')
49
49
 
50
50
  module EntitySpec
@@ -75,7 +75,7 @@ describe Grape::Entity do
75
75
  end
76
76
 
77
77
  it 'pulls a representation from the class ancestor if it exists' do
78
- entity = Class.new(Grape::Entity)
78
+ entity = Class.new(described_class)
79
79
  allow(entity).to receive(:represent).and_return('Hiya')
80
80
 
81
81
  subclass = Class.new(Object)
@@ -90,7 +90,7 @@ describe Grape::Entity do
90
90
 
91
91
  it 'automatically uses Klass::Entity if that exists' do
92
92
  some_model = Class.new
93
- entity = Class.new(Grape::Entity)
93
+ entity = Class.new(described_class)
94
94
  allow(entity).to receive(:represent).and_return('Auto-detect!')
95
95
 
96
96
  some_model.const_set :Entity, entity
@@ -104,7 +104,7 @@ describe Grape::Entity do
104
104
 
105
105
  it 'automatically uses Klass::Entity based on the first object in the collection being presented' do
106
106
  some_model = Class.new
107
- entity = Class.new(Grape::Entity)
107
+ entity = Class.new(described_class)
108
108
  allow(entity).to receive(:represent).and_return('Auto-detect!')
109
109
 
110
110
  some_model.const_set :Entity, entity
@@ -117,7 +117,7 @@ describe Grape::Entity do
117
117
  end
118
118
 
119
119
  it 'does not run autodetection for Entity when explicitly provided' do
120
- entity = Class.new(Grape::Entity)
120
+ entity = Class.new(described_class)
121
121
  some_array = []
122
122
 
123
123
  subject.get '/example' do
@@ -129,7 +129,7 @@ describe Grape::Entity do
129
129
  end
130
130
 
131
131
  it 'does not use #first method on ActiveRecord::Relation to prevent needless sql query' do
132
- entity = Class.new(Grape::Entity)
132
+ entity = Class.new(described_class)
133
133
  some_relation = Class.new
134
134
  some_model = Class.new
135
135
 
@@ -173,7 +173,7 @@ describe Grape::Entity do
173
173
 
174
174
  %i[json serializable_hash].each do |format|
175
175
  it "presents with #{format}" do
176
- entity = Class.new(Grape::Entity)
176
+ entity = Class.new(described_class)
177
177
  entity.root 'examples', 'example'
178
178
  entity.expose :id
179
179
 
@@ -195,7 +195,7 @@ describe Grape::Entity do
195
195
  end
196
196
 
197
197
  it "presents with #{format} collection" do
198
- entity = Class.new(Grape::Entity)
198
+ entity = Class.new(described_class)
199
199
  entity.root 'examples', 'example'
200
200
  entity.expose :id
201
201
 
@@ -219,7 +219,7 @@ describe Grape::Entity do
219
219
  end
220
220
 
221
221
  it 'presents with xml' do
222
- entity = Class.new(Grape::Entity)
222
+ entity = Class.new(described_class)
223
223
  entity.root 'examples', 'example'
224
224
  entity.expose :name
225
225
 
@@ -238,18 +238,18 @@ describe Grape::Entity do
238
238
  get '/example'
239
239
  expect(last_response.status).to eq(200)
240
240
  expect(last_response.headers['Content-type']).to eq('application/xml')
241
- expect(last_response.body).to eq <<-XML
242
- <?xml version="1.0" encoding="UTF-8"?>
243
- <hash>
244
- <example>
245
- <name>johnnyiller</name>
246
- </example>
247
- </hash>
248
- XML
241
+ expect(last_response.body).to eq <<~XML
242
+ <?xml version="1.0" encoding="UTF-8"?>
243
+ <hash>
244
+ <example>
245
+ <name>johnnyiller</name>
246
+ </example>
247
+ </hash>
248
+ XML
249
249
  end
250
250
 
251
251
  it 'presents with json' do
252
- entity = Class.new(Grape::Entity)
252
+ entity = Class.new(described_class)
253
253
  entity.root 'examples', 'example'
254
254
  entity.expose :name
255
255
 
@@ -275,7 +275,7 @@ XML
275
275
  # Include JSONP middleware
276
276
  subject.use Rack::JSONP
277
277
 
278
- entity = Class.new(Grape::Entity)
278
+ entity = Class.new(described_class)
279
279
  entity.root 'examples', 'example'
280
280
  entity.expose :name
281
281
 
@@ -315,7 +315,7 @@ XML
315
315
  user1 = user.new(name: 'user1')
316
316
  user2 = user.new(name: 'user2')
317
317
 
318
- entity = Class.new(Grape::Entity)
318
+ entity = Class.new(described_class)
319
319
  entity.expose :name
320
320
 
321
321
  subject.format :json
@@ -326,7 +326,7 @@ XML
326
326
  end
327
327
  get '/example'
328
328
  expect_response_json = {
329
- 'page' => 1,
329
+ 'page' => 1,
330
330
  'user1' => { 'name' => 'user1' },
331
331
  'user2' => { 'name' => 'user2' }
332
332
  }
@@ -5,6 +5,7 @@ require 'spec_helper'
5
5
  describe Grape::Exceptions::ValidationErrors do
6
6
  context 'api with rescue_from :all handler' do
7
7
  subject { Class.new(Grape::API) }
8
+
8
9
  before do
9
10
  subject.rescue_from :all do |_e|
10
11
  rack_response 'message was processed', 400
@@ -56,6 +57,7 @@ describe Grape::Exceptions::ValidationErrors do
56
57
 
57
58
  context 'api with rescue_from :grape_exceptions handler' do
58
59
  subject { Class.new(Grape::API) }
60
+
59
61
  before do
60
62
  subject.rescue_from :all do |_e|
61
63
  rack_response 'message was processed', 400
@@ -93,6 +95,7 @@ describe Grape::Exceptions::ValidationErrors do
93
95
 
94
96
  context 'api without a rescue handler' do
95
97
  subject { Class.new(Grape::API) }
98
+
96
99
  before do
97
100
  subject.params do
98
101
  requires :beer