grape 0.16.1 → 0.16.2

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
2
  SHA1:
3
- metadata.gz: 14025980d9a1ead68f6864f6794d94cb4a070b8c
4
- data.tar.gz: 0cb0c1aa236b361ff803d2534f545542016503dc
3
+ metadata.gz: 5c0353f686611ae4c8f0b58a8cbe67a8a75517b2
4
+ data.tar.gz: 4df3e13972d076ebc707112bc5a8a837a022ef77
5
5
  SHA512:
6
- metadata.gz: 0530cb22cb08ab580a4450a0b4e7d9337cb5d0ae920cdd6c00124d8c238e4b4be24f0cdfc759caf343135c479c45da64fba8f8214ddb88a7ec88aa709a7392c1
7
- data.tar.gz: d467e07232bc21fe849ec5a122126f119e1fee53cebfc5691a1ce8c9b6f90c75072dfae88ff50f116457f0e0c4cb7100e75358415a549d14b37d1e46aca3e3ea
6
+ metadata.gz: 5617f40d20408389c2cac83277cf87865bf3103d7606fff84c0dfd6349d577fe3aea9b1649dc716b929e4631d1a45ad15df96a4e8d1766f8c16e66333a97668c
7
+ data.tar.gz: c761206de05d16b81b4875dd3c57aa62b5ea5b0c0e301b53321f308ff45ba19c2e9437734020d0ad3a52c7f56763cb81a390f82fb50dc70d537c0cb0edfee883
@@ -1,3 +1,17 @@
1
+ 0.16.2 (4/12/2016)
2
+ ==================
3
+
4
+ #### Features
5
+
6
+ * [#1348](https://github.com/ruby-grape/grape/pull/1348): Fix global functions polluting Grape::API scope - [@dblock](https://github.com/dblock).
7
+ * [#1357](https://github.com/ruby-grape/grape/pull/1357): Expose Route#options - [@namusyaka](https://github.com/namusyaka).
8
+
9
+ #### Fixes
10
+
11
+ * [#1357](https://github.com/ruby-grape/grape/pull/1357): Don't include fixed named captures as route params - [@namusyaka](https://github.com/namusyaka).
12
+ * [#1359](https://github.com/ruby-grape/grape/pull/1359): Avoid evaluating the same route twice - [@namusyaka](https://github.com/namusyaka), [@dblock](https://github.com/dblock).
13
+ * [#1361](https://github.com/ruby-grape/grape/pull/1361): Return 405 correctly even if version is using as header and wrong request method - [@namusyaka](https://github.com/namusyaka), [@dblock](https://github.com/dblock).
14
+
1
15
  0.16.1 (4/3/2016)
2
16
  =================
3
17
 
@@ -43,6 +57,7 @@
43
57
  * [#1197](https://github.com/ruby-grape/grape/pull/1290): Fix using JSON and Array[JSON] as groups when parameter is optional - [@lukeivers](https://github.com/lukeivers).
44
58
 
45
59
  0.14.0 (12/07/2015)
60
+ =================
46
61
 
47
62
  #### Features
48
63
 
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- grape (0.16.1)
4
+ grape (0.16.2)
5
5
  activesupport
6
6
  builder
7
7
  hashie (>= 2.1.0)
@@ -150,7 +150,7 @@ DEPENDENCIES
150
150
  bundler
151
151
  cookiejar
152
152
  grape!
153
- grape-entity (>= 0.4.4)
153
+ grape-entity (= 0.5.0)
154
154
  guard
155
155
  guard-rspec
156
156
  guard-rubocop
data/README.md CHANGED
@@ -103,7 +103,7 @@ content negotiation, versioning and much more.
103
103
 
104
104
  ## Stable Release
105
105
 
106
- You're reading the documentation for the stable release of Grape, 0.16.1.
106
+ You're reading the documentation for the stable release of Grape, 0.16.2.
107
107
  Please read [UPGRADING](UPGRADING.md) when upgrading from a previous version.
108
108
 
109
109
  ## Project Resources
@@ -2566,6 +2566,11 @@ Note that `Route#route_xyz` methods have been deprecated since 0.15.0.
2566
2566
 
2567
2567
  Please use `Route#xyz` instead.
2568
2568
 
2569
+ Note that difference of `Route#options` and `Route#settings`.
2570
+
2571
+ The `options` can be referred from your route, it should be set by specifing key and value on verb methods such as `get`, `post` and `put`.
2572
+ The `settings` can also be referred from your route, but it should be set by specifing key and value on `route_setting`.
2573
+
2569
2574
  ## Current Route and Endpoint
2570
2575
 
2571
2576
  It's possible to retrieve the information about the current route from within an API call with `route`.
@@ -22,7 +22,7 @@ Gem::Specification.new do |s|
22
22
  s.add_runtime_dependency 'virtus', '>= 1.0.0'
23
23
  s.add_runtime_dependency 'builder'
24
24
 
25
- s.add_development_dependency 'grape-entity', '>= 0.4.4'
25
+ s.add_development_dependency 'grape-entity', '0.5.0'
26
26
  s.add_development_dependency 'rake', '~> 10'
27
27
  s.add_development_dependency 'maruku'
28
28
  s.add_development_dependency 'yard'
@@ -231,7 +231,7 @@ module Grape
231
231
 
232
232
  run_filters before_validations, :before_validation
233
233
 
234
- run_validators validations, request unless @method_not_allowed
234
+ run_validators validations, request unless env[Grape::Env::GRAPE_METHOD_NOT_ALLOWED]
235
235
 
236
236
  run_filters after_validations, :after_validation
237
237
 
@@ -32,7 +32,7 @@ module Grape
32
32
  def before
33
33
  strict_header_checks if strict?
34
34
 
35
- if media_type
35
+ if media_type || env[Grape::Env::GRAPE_METHOD_NOT_ALLOWED]
36
36
  media_type_header_handler
37
37
  elsif headers_contain_wrong_vendor?
38
38
  fail_with_invalid_accept_header!('API vendor not found.')
@@ -41,7 +41,8 @@ module Grape
41
41
 
42
42
  def call(env)
43
43
  with_optimization do
44
- identity(env) || rotation(env) { |route| route.exec(env) }
44
+ response, route = identity(env)
45
+ response || rotation(env, route)
45
46
  end
46
47
  end
47
48
 
@@ -54,26 +55,28 @@ module Grape
54
55
  private
55
56
 
56
57
  def identity(env)
57
- transaction(env) do |input, method, routing_args|
58
+ route = nil
59
+ response = transaction(env) do |input, method, routing_args|
58
60
  route = match?(input, method)
59
61
  if route
60
62
  env[Grape::Env::GRAPE_ROUTING_ARGS] = make_routing_args(routing_args, route, input)
61
63
  route.exec(env)
62
64
  end
63
65
  end
66
+ [response, route]
64
67
  end
65
68
 
66
- def rotation(env)
67
- transaction(env) do |input, method, routing_args|
68
- response = nil
69
- routes_for(method).each do |route|
70
- next unless route.match?(input)
71
- env[Grape::Env::GRAPE_ROUTING_ARGS] = make_routing_args(routing_args, route, input)
72
- response = yield(route)
73
- break unless cascade?(response)
74
- end
75
- response
69
+ def rotation(env, exact_route = nil)
70
+ response = nil
71
+ input, method, routing_args = *extract_required_args(env)
72
+ routes_for(method).each do |route|
73
+ next if exact_route == route
74
+ next unless route.match?(input)
75
+ env[Grape::Env::GRAPE_ROUTING_ARGS] = make_routing_args(routing_args, route, input)
76
+ response = route.exec(env)
77
+ break unless cascade?(response)
76
78
  end
79
+ response
77
80
  end
78
81
 
79
82
  def transaction(env)
@@ -122,10 +125,12 @@ module Grape
122
125
  end
123
126
 
124
127
  def method_not_allowed(env, methods, endpoint)
128
+ env[Grape::Env::GRAPE_METHOD_NOT_ALLOWED] = true
125
129
  current = endpoint.dup
126
130
  current.instance_eval do
131
+ @lazy_initialized = false
132
+ lazy_initialize!
127
133
  run_filters befores, :before
128
- @method_not_allowed = true
129
134
  @block = proc do
130
135
  fail Grape::Exceptions::MethodNotAllowed, header.merge('Allow' => methods)
131
136
  end
@@ -1,39 +1,29 @@
1
- require 'delegate'
2
- require 'ostruct'
3
-
4
1
  module Grape
5
2
  class Router
6
- class AttributeTranslator < DelegateClass(OpenStruct)
7
- def self.register(*attributes)
8
- AttributeTranslator.supported_attributes.concat(attributes)
9
- end
10
-
11
- def self.supported_attributes
12
- @supported_attributes ||= []
13
- end
14
-
3
+ # this could be an OpenStruct, but doesn't work in Ruby 2.3.0, see https://bugs.ruby-lang.org/issues/12251
4
+ class AttributeTranslator
15
5
  def initialize(attributes = {})
16
- ostruct = OpenStruct.new(attributes)
17
- super ostruct
18
6
  @attributes = attributes
19
- self.class.supported_attributes.each do |name|
20
- ostruct.send(:"#{name}=", nil) unless ostruct.respond_to?(name)
21
- self.class.instance_eval do
22
- define_method(name) { instance_variable_get(:"@#{name}") }
23
- end if name == :format
24
- end
25
7
  end
26
8
 
27
9
  def to_h
28
- @attributes.each_with_object({}) do |(key, _), attributes|
29
- attributes[key.to_sym] = send(:"#{key}")
30
- end
10
+ @attributes
31
11
  end
32
12
 
33
- private
13
+ def method_missing(m, *args)
14
+ if m[-1] == '='
15
+ @attributes[m[0..-1]] = *args
16
+ else
17
+ @attributes[m]
18
+ end
19
+ end
34
20
 
35
- def accessor_available?(name)
36
- respond_to?(name) && respond_to?(:"#{name}=")
21
+ def respond_to_missing?(method_name, _include_private = false)
22
+ if method_name[-1] == '='
23
+ true
24
+ else
25
+ @attributes.key?(method_name)
26
+ end
37
27
  end
38
28
  end
39
29
  end
@@ -8,35 +8,15 @@ module Grape
8
8
  class Route
9
9
  ROUTE_ATTRIBUTE_REGEXP = /route_([_a-zA-Z]\w*)/.freeze
10
10
  SOURCE_LOCATION_REGEXP = /^(.*?):(\d+?)(?::in `.+?')?$/.freeze
11
- TRANSLATION_ATTRIBUTES = [
12
- :prefix,
13
- :version,
14
- :namespace,
15
- :settings,
16
- :format,
17
- :description,
18
- :http_codes,
19
- :headers,
20
- :entity,
21
- :details,
22
- :requirements,
23
- :request_method
24
- ].freeze
11
+ FIXED_NAMED_CAPTURES = %w(format version).freeze
25
12
 
26
- attr_accessor :pattern, :translator, :app, :index, :regexp
13
+ attr_accessor :pattern, :translator, :app, :index, :regexp, :options
27
14
 
28
15
  alias_method :attributes, :translator
29
16
 
30
17
  extend Forwardable
31
18
  def_delegators :pattern, :path, :origin
32
19
 
33
- def self.translate(*attributes)
34
- AttributeTranslator.register(*attributes)
35
- def_delegators :@translator, *attributes
36
- end
37
-
38
- translate(*TRANSLATION_ATTRIBUTES)
39
-
40
20
  def method_missing(method_id, *arguments)
41
21
  match = ROUTE_ATTRIBUTE_REGEXP.match(method_id.to_s)
42
22
  if match
@@ -48,6 +28,25 @@ module Grape
48
28
  end
49
29
  end
50
30
 
31
+ [
32
+ :prefix,
33
+ :version,
34
+ :settings,
35
+ :format,
36
+ :description,
37
+ :http_codes,
38
+ :headers,
39
+ :entity,
40
+ :details,
41
+ :requirements,
42
+ :request_method,
43
+ :namespace
44
+ ].each do |method_name|
45
+ define_method method_name do
46
+ attributes.public_send method_name
47
+ end
48
+ end
49
+
51
50
  def route_method
52
51
  warn_route_methods(:method, caller(1).shift, :request_method)
53
52
  request_method
@@ -80,10 +79,9 @@ module Grape
80
79
 
81
80
  def params(input = nil)
82
81
  if input.nil?
83
- default = pattern.named_captures.keys.each_with_object({}) do |key, defaults|
84
- defaults[key] = ''
82
+ pattern.named_captures.keys.each_with_object(translator.params) do |(key), defaults|
83
+ defaults[key] ||= '' unless FIXED_NAMED_CAPTURES.include?(key) || defaults.key?(key)
85
84
  end
86
- default.delete_if { |key, _| key == 'format' }.merge(translator.params)
87
85
  else
88
86
  parsed = pattern.params(input)
89
87
  parsed ? parsed.delete_if { |_, value| value.nil? }.symbolize_keys : {}
@@ -18,5 +18,6 @@ module Grape
18
18
  GRAPE_REQUEST_HEADERS = 'grape.request.headers'.freeze
19
19
  GRAPE_REQUEST_PARAMS = 'grape.request.params'.freeze
20
20
  GRAPE_ROUTING_ARGS = 'grape.routing_args'.freeze
21
+ GRAPE_METHOD_NOT_ALLOWED = 'grape.method_not_allowed'.freeze
21
22
  end
22
23
  end
@@ -1,4 +1,4 @@
1
1
  module Grape
2
2
  # The current version of Grape.
3
- VERSION = '0.16.1'
3
+ VERSION = '0.16.2'
4
4
  end
Binary file
@@ -0,0 +1,24 @@
1
+ diff --git lib/grape/router/route.rb lib/grape/router/route.rb
2
+ index 643960d..1074c01 100644
3
+ --- lib/grape/router/route.rb
4
+ +++ lib/grape/router/route.rb
5
+ @@ -20,7 +20,9 @@ module Grape
6
+ :entity,
7
+ :details,
8
+ :requirements,
9
+ - :request_method
10
+ + :request_method,
11
+ + :hidden,
12
+ + :params
13
+ ].freeze
14
+
15
+ attr_accessor :pattern, :translator, :app, :index, :regexp
16
+ @@ -42,7 +44,7 @@ module Grape
17
+ if match
18
+ method_name = match.captures.last.to_sym
19
+ warn_route_methods(method_name, caller(1).shift)
20
+ - @options[method_name]
21
+ + respond_to?(method_name) ? send(method_name) : @options[method_name]
22
+ else
23
+ super
24
+ end
@@ -0,0 +1,80 @@
1
+ require 'spec_helper'
2
+
3
+ describe Grape::API::Helpers do
4
+ module PatchHelpersSpec
5
+ class PatchPublic < Grape::API
6
+ format :json
7
+ version 'public-v1', using: :header, vendor: 'grape'
8
+
9
+ get do
10
+ { ok: 'public' }
11
+ end
12
+ end
13
+
14
+ module AuthMethods
15
+ def authenticate!
16
+ end
17
+ end
18
+
19
+ class PatchPrivate < Grape::API
20
+ format :json
21
+ version 'private-v1', using: :header, vendor: 'grape'
22
+
23
+ helpers AuthMethods
24
+
25
+ before do
26
+ authenticate!
27
+ end
28
+
29
+ get do
30
+ { ok: 'private' }
31
+ end
32
+ end
33
+
34
+ class Main < Grape::API
35
+ mount PatchPublic
36
+ mount PatchPrivate
37
+ end
38
+ end
39
+
40
+ def app
41
+ PatchHelpersSpec::Main
42
+ end
43
+
44
+ context 'patch' do
45
+ it 'public' do
46
+ patch '/', {}, 'HTTP_ACCEPT' => 'application/vnd.grape-public-v1+json'
47
+ expect(last_response.status).to eq 405
48
+ end
49
+
50
+ it 'private' do
51
+ patch '/', {}, 'HTTP_ACCEPT' => 'application/vnd.grape-private-v1+json'
52
+ expect(last_response.status).to eq 405
53
+ end
54
+
55
+ it 'default' do
56
+ patch '/'
57
+ expect(last_response.status).to eq 405
58
+ end
59
+ end
60
+
61
+ context 'default' do
62
+ it 'public' do
63
+ get '/', {}, 'HTTP_ACCEPT' => 'application/vnd.grape-public-v1+json'
64
+ expect(last_response.status).to eq 200
65
+ expect(last_response.body).to eq({ ok: 'public' }.to_json)
66
+ end
67
+
68
+ it 'private' do
69
+ get '/', {}, 'HTTP_ACCEPT' => 'application/vnd.grape-private-v1+json'
70
+ expect(last_response.status).to eq 200
71
+ expect(last_response.body).to eq({ ok: 'private' }.to_json)
72
+ end
73
+
74
+ it 'default' do
75
+ get '/'
76
+ expect(last_response.status).to eq 200
77
+ expect(last_response.body).to eq({ ok: 'public' }.to_json)
78
+ end
79
+ end
80
+ end
@@ -2256,6 +2256,14 @@ XML
2256
2256
  expect(route.description).to eq('first method')
2257
2257
  expect(route.route_foo).to be_nil
2258
2258
  expect(route.params).to eq({})
2259
+ expect(route.options).to be_a_kind_of(Hash)
2260
+ end
2261
+ it 'has params which does not include format and version as named captures' do
2262
+ subject.version :v1, using: :path
2263
+ subject.get :first do; end
2264
+ param_keys = subject.routes.first.params.keys
2265
+ expect(param_keys).not_to include('format')
2266
+ expect(param_keys).not_to include('version')
2259
2267
  end
2260
2268
  it 'describes methods separately' do
2261
2269
  subject.desc 'first method'
@@ -0,0 +1,29 @@
1
+ # see https://github.com/ruby-grape/grape/issues/1348
2
+
3
+ require 'spec_helper'
4
+
5
+ def namespace
6
+ fail
7
+ end
8
+
9
+ describe Grape::API do
10
+ subject do
11
+ Class.new(Grape::API) do
12
+ format :json
13
+ get do
14
+ { ok: true }
15
+ end
16
+ end
17
+ end
18
+
19
+ def app
20
+ subject
21
+ end
22
+
23
+ context 'with a global namespace function' do
24
+ it 'works' do
25
+ get '/'
26
+ expect(last_response.status).to eq 200
27
+ end
28
+ end
29
+ end
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: 0.16.1
4
+ version: 0.16.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Bleigh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-04-02 00:00:00.000000000 Z
11
+ date: 2016-04-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -140,16 +140,16 @@ dependencies:
140
140
  name: grape-entity
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
- - - ">="
143
+ - - '='
144
144
  - !ruby/object:Gem::Version
145
- version: 0.4.4
145
+ version: 0.5.0
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
- - - ">="
150
+ - - '='
151
151
  - !ruby/object:Gem::Version
152
- version: 0.4.4
152
+ version: 0.5.0
153
153
  - !ruby/object:Gem::Dependency
154
154
  name: rake
155
155
  requirement: !ruby/object:Gem::Requirement
@@ -453,12 +453,15 @@ files:
453
453
  - lib/grape/validations/validators/regexp.rb
454
454
  - lib/grape/validations/validators/values.rb
455
455
  - lib/grape/version.rb
456
+ - pkg/grape-0.16.1.gem
457
+ - pkg/patch.diff
456
458
  - spec/grape/api/custom_validations_spec.rb
457
459
  - spec/grape/api/deeply_included_options_spec.rb
458
460
  - spec/grape/api/invalid_format_spec.rb
459
461
  - spec/grape/api/namespace_parameters_in_route_spec.rb
460
462
  - spec/grape/api/nested_helpers_spec.rb
461
463
  - spec/grape/api/optional_parameters_in_route_spec.rb
464
+ - spec/grape/api/patch_method_helpers_spec.rb
462
465
  - spec/grape/api/recognize_path_spec.rb
463
466
  - spec/grape/api/required_parameters_in_route_spec.rb
464
467
  - spec/grape/api/required_parameters_with_invalid_method_spec.rb
@@ -489,6 +492,7 @@ files:
489
492
  - spec/grape/exceptions/unknown_validator_spec.rb
490
493
  - spec/grape/exceptions/validation_errors_spec.rb
491
494
  - spec/grape/exceptions/validation_spec.rb
495
+ - spec/grape/integration/global_namespace_function_spec.rb
492
496
  - spec/grape/integration/rack_sendfile_spec.rb
493
497
  - spec/grape/integration/rack_spec.rb
494
498
  - spec/grape/loading_spec.rb
@@ -556,7 +560,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
556
560
  version: '0'
557
561
  requirements: []
558
562
  rubyforge_project:
559
- rubygems_version: 2.4.5.1
563
+ rubygems_version: 2.5.1
560
564
  signing_key:
561
565
  specification_version: 4
562
566
  summary: A simple Ruby framework for building REST-like APIs.
@@ -567,6 +571,7 @@ test_files:
567
571
  - spec/grape/api/namespace_parameters_in_route_spec.rb
568
572
  - spec/grape/api/nested_helpers_spec.rb
569
573
  - spec/grape/api/optional_parameters_in_route_spec.rb
574
+ - spec/grape/api/patch_method_helpers_spec.rb
570
575
  - spec/grape/api/recognize_path_spec.rb
571
576
  - spec/grape/api/required_parameters_in_route_spec.rb
572
577
  - spec/grape/api/required_parameters_with_invalid_method_spec.rb
@@ -597,6 +602,7 @@ test_files:
597
602
  - spec/grape/exceptions/unknown_validator_spec.rb
598
603
  - spec/grape/exceptions/validation_errors_spec.rb
599
604
  - spec/grape/exceptions/validation_spec.rb
605
+ - spec/grape/integration/global_namespace_function_spec.rb
600
606
  - spec/grape/integration/rack_sendfile_spec.rb
601
607
  - spec/grape/integration/rack_spec.rb
602
608
  - spec/grape/loading_spec.rb