grape-path-helpers 1.1.0 → 1.6.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e5de62b3e52c6df10f69653f7aad9f4c81a64298c4ad74eb0085b06985a98474
4
- data.tar.gz: bc29c3966d9f85de40b845d9e071fce2bc869d73776ce95078816c6f553a0494
3
+ metadata.gz: 40792c146fc9c26dd609bc8dd99adce92b010820e3c2ca9644144f3493dd06ec
4
+ data.tar.gz: aed680f63272f1e61467787e0d374bb8a8145b61979c18b5c61e332763472cd5
5
5
  SHA512:
6
- metadata.gz: 04bb77b1e0ee4b792ca6edc6ce1dfd1a18f9af85bc828f2e5f384f621f5ad42a7ad16e2712e9dfb50c8f8e2e8229e5947279122888169eeaeaf12d78860d64fc
7
- data.tar.gz: 0bfc95924b6ed43d02c39c6f77123c047122d2cfebc762745362273c837950e568fb22894008cd729de90a17373ea48d2dd933a8e9b85d5b7acdfab156aa836d
6
+ metadata.gz: ff06e53d14f8d46a398cc14754fbc61e7e1a1e28179aa83a27bbca47698c117daaf064f62d3e03e1a385112fea2c0dd076b102e64e4c2f1ffa3c4d4fae7d3279
7
+ data.tar.gz: 82fde6483c7ad996189c59ab9c79969495e642fb0274d9e209228b6633e6c6c731066a4bf24effa6e00e990f3fc82b94eca8084b469f64aad15e8f9a5f486728
@@ -1,8 +1,9 @@
1
- image: "ruby:2.4-alpine"
1
+ image: "ruby:3.0-alpine"
2
2
 
3
3
  cache:
4
4
  paths:
5
5
  - vendor/ruby
6
+ key: ruby-3.0
6
7
 
7
8
  before_script:
8
9
  - apk add --update git
@@ -8,3 +8,7 @@ Metrics/MethodLength:
8
8
 
9
9
  Style/FileName:
10
10
  Enabled: false
11
+
12
+ # Removed in newer versions of Rubocop
13
+ Lint/SplatKeywordArguments:
14
+ Enabled: false
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.6.0
4
+
5
+ * [Extract kwargs to fix 2.7 warnings](https://gitlab.com/gitlab-org/grape-path-helpers/-/merge_requests/29)
6
+
7
+ ## 1.5.0
8
+
9
+ * [Relax rake dependency](https://gitlab.com/gitlab-org/grape-path-helpers/-/merge_requests/27)
10
+
11
+ ## 1.4.0
12
+
13
+ * [Support using a base class other than Grape::API::Instance](https://gitlab.com/gitlab-org/grape-path-helpers/-/merge_requests/23)
14
+
15
+ ## 1.3.0
16
+
17
+ * [Upgrade to Grape 1.3.1](https://gitlab.com/gitlab-org/grape-path-helpers/-/merge_requests/21)
18
+
19
+ ## 1.2.0
20
+
21
+ * [Add wildcard segments support](https://gitlab.com/gitlab-org/grape-path-helpers/merge_requests/16)
22
+
3
23
  ## 1.1.0
4
24
 
5
25
  * [Relax dependency on ActiveSupport](https://gitlab.com/gitlab-org/grape-path-helpers/merge_requests/12)
@@ -1,48 +1,60 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- grape-path-helpers (1.0.6)
5
- activesupport (>= 4, < 5.1)
6
- grape (~> 1.0)
7
- rake (~> 12)
4
+ grape-path-helpers (1.6.0)
5
+ activesupport
6
+ grape (~> 1.3)
7
+ rake (> 12)
8
8
 
9
9
  GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
- activesupport (5.0.7)
12
+ activesupport (6.1.1)
13
13
  concurrent-ruby (~> 1.0, >= 1.0.2)
14
- i18n (>= 0.7, < 2)
15
- minitest (~> 5.1)
16
- tzinfo (~> 1.1)
14
+ i18n (>= 1.6, < 2)
15
+ minitest (>= 5.1)
16
+ tzinfo (~> 2.0)
17
+ zeitwerk (~> 2.3)
17
18
  ast (2.4.0)
18
- axiom-types (0.1.1)
19
- descendants_tracker (~> 0.0.4)
20
- ice_nine (~> 0.11.0)
21
- thread_safe (~> 0.3, >= 0.3.1)
22
- builder (3.2.3)
19
+ builder (3.2.4)
23
20
  coderay (1.1.2)
24
- coercible (1.0.0)
25
- descendants_tracker (~> 0.0.1)
26
- concurrent-ruby (1.0.5)
27
- descendants_tracker (0.0.4)
28
- thread_safe (~> 0.3, >= 0.3.1)
21
+ concurrent-ruby (1.1.7)
29
22
  diff-lcs (1.3)
30
- equalizer (0.0.11)
31
- grape (1.0.3)
23
+ dry-configurable (0.12.0)
24
+ concurrent-ruby (~> 1.0)
25
+ dry-core (~> 0.5, >= 0.5.0)
26
+ dry-container (0.7.2)
27
+ concurrent-ruby (~> 1.0)
28
+ dry-configurable (~> 0.1, >= 0.1.3)
29
+ dry-core (0.5.0)
30
+ concurrent-ruby (~> 1.0)
31
+ dry-equalizer (0.3.0)
32
+ dry-inflector (0.2.0)
33
+ dry-logic (1.1.0)
34
+ concurrent-ruby (~> 1.0)
35
+ dry-core (~> 0.5, >= 0.5)
36
+ dry-types (1.4.0)
37
+ concurrent-ruby (~> 1.0)
38
+ dry-container (~> 0.3)
39
+ dry-core (~> 0.4, >= 0.4.4)
40
+ dry-equalizer (~> 0.3)
41
+ dry-inflector (~> 0.1, >= 0.1.2)
42
+ dry-logic (~> 1.0, >= 1.0.2)
43
+ grape (1.5.1)
32
44
  activesupport
33
45
  builder
46
+ dry-types (>= 1.1)
34
47
  mustermann-grape (~> 1.0.0)
35
48
  rack (>= 1.3.0)
36
49
  rack-accept
37
- virtus (>= 1.0.0)
38
- i18n (1.0.1)
50
+ i18n (1.8.7)
39
51
  concurrent-ruby (~> 1.0)
40
- ice_nine (0.11.2)
41
52
  method_source (0.9.0)
42
- minitest (5.11.3)
43
- mustermann (1.0.2)
44
- mustermann-grape (1.0.0)
45
- mustermann (~> 1.0.0)
53
+ minitest (5.14.3)
54
+ mustermann (1.1.1)
55
+ ruby2_keywords (~> 0.0.1)
56
+ mustermann-grape (1.0.1)
57
+ mustermann (>= 1.0.0)
46
58
  parallel (1.12.1)
47
59
  parser (2.5.1.0)
48
60
  ast (~> 2.4.0)
@@ -50,11 +62,11 @@ GEM
50
62
  pry (0.11.3)
51
63
  coderay (~> 1.1.0)
52
64
  method_source (~> 0.9.0)
53
- rack (2.0.5)
65
+ rack (2.2.3)
54
66
  rack-accept (0.4.5)
55
67
  rack (>= 0.4)
56
68
  rainbow (3.0.0)
57
- rake (12.3.1)
69
+ rake (13.0.3)
58
70
  rspec (3.7.0)
59
71
  rspec-core (~> 3.7.0)
60
72
  rspec-expectations (~> 3.7.0)
@@ -76,15 +88,11 @@ GEM
76
88
  ruby-progressbar (~> 1.7)
77
89
  unicode-display_width (~> 1.0, >= 1.0.1)
78
90
  ruby-progressbar (1.9.0)
79
- thread_safe (0.3.6)
80
- tzinfo (1.2.5)
81
- thread_safe (~> 0.1)
91
+ ruby2_keywords (0.0.2)
92
+ tzinfo (2.0.4)
93
+ concurrent-ruby (~> 1.0)
82
94
  unicode-display_width (1.3.3)
83
- virtus (1.0.5)
84
- axiom-types (~> 0.1)
85
- coercible (~> 1.0)
86
- descendants_tracker (~> 0.0, >= 0.0.3)
87
- equalizer (~> 0.0, >= 0.0.9)
95
+ zeitwerk (2.4.2)
88
96
 
89
97
  PLATFORMS
90
98
  ruby
@@ -96,4 +104,4 @@ DEPENDENCIES
96
104
  rubocop (~> 0.56)
97
105
 
98
106
  BUNDLED WITH
99
- 1.16.2
107
+ 2.2.3
@@ -1,6 +1,7 @@
1
1
  MIT License (MIT)
2
2
 
3
- Copyright (c) 2015 Harper Henn
3
+ Copyright (c) 2015,2016 Harper Henn
4
+ Copyright (c) 2018-2020 GitLab B.V.
4
5
 
5
6
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
7
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # grape-path-helpers
2
2
 
3
- [![Build status](https://gitlab.com/gitlab-org/grape-path-helpers/badges/master/build.svg)](https://gitlab.com/gitlab-org/grape-path-helpers/commits/master)
3
+ [![Build status](https://gitlab.com/gitlab-org/grape-path-helpers/badges/master/pipeline.svg)](https://gitlab.com/gitlab-org/grape-path-helpers/commits/master)
4
4
 
5
5
  Provides named route helpers for Grape APIs, similar to [Rails' route helpers](http://edgeguides.rubyonrails.org/routing.html#path-and-url-helpers).
6
6
 
7
- **This is a fork and rename of [group-route-helpers](https://github.com/reprah/grape-route-helpers). It [includes some fixes](CHANGELOG.md) needed for GitLab.**
7
+ **This is a fork and rename of [grape-route-helpers](https://github.com/reprah/grape-route-helpers). It [includes some fixes](CHANGELOG.md) needed for GitLab.**
8
8
 
9
9
  ### Installation
10
10
 
@@ -76,7 +76,7 @@ You can use helper methods in your REPL session by including a module:
76
76
  Use the methods inside your Grape API actions. Given this example API:
77
77
 
78
78
  ```ruby
79
- class ExampleAPI < Grape::API
79
+ class ExampleAPI < Grape::API::Instance
80
80
  version 'v1'
81
81
  prefix 'api'
82
82
  format 'json'
@@ -127,7 +127,7 @@ api_v1_anything_path # => '/api/v1/*anything'
127
127
  If you want to assign a custom helper name to a route, pass the `:as` option when creating your route in your API:
128
128
 
129
129
  ```ruby
130
- class Base < Grape::API
130
+ class Base < Grape::API::Instance
131
131
  get 'ping', as: 'is_the_server_running'
132
132
  'pong'
133
133
  end
@@ -169,6 +169,14 @@ end
169
169
 
170
170
  6.) Create a new pull request
171
171
 
172
+ ### Releasing
173
+
174
+ 1. Update the [CHANGELOG](CHANGELOG.md).
175
+ 2. Update the version in [lib/grape-path-helpers/version.rb](lib/grape-path-helpers/version.rb).
176
+ 3. [Tag](https://gitlab.com/gitlab-org/grape-path-helpers/-/tags) the commit with the version number prefixed by 'v'.
177
+ 4. Run `gem build grape-path-helpers` locally.
178
+ 5. Run `gem push $new_file.gem` locally, where `$new_file` is the file generated by the step above.
179
+
172
180
  ### License
173
181
 
174
182
  See LICENSE
data/Rakefile CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'rubygems'
2
2
  require 'bundler'
3
+ require 'bundler/gem_tasks'
3
4
 
4
5
  Bundler.setup :default, :test, :development
5
6
 
@@ -12,8 +12,8 @@ Gem::Specification.new do |gem|
12
12
  gem.homepage = 'https://gitlab.com/gitlab-org/grape-path-helpers'
13
13
 
14
14
  gem.add_runtime_dependency 'activesupport'
15
- gem.add_runtime_dependency 'grape', '~> 1.0'
16
- gem.add_runtime_dependency 'rake', '~> 12'
15
+ gem.add_runtime_dependency 'grape', '~> 1.3'
16
+ gem.add_runtime_dependency 'rake', '> 12'
17
17
 
18
18
  gem.add_development_dependency 'pry', '~> 0.11'
19
19
  gem.add_development_dependency 'rspec', '~> 3.7'
@@ -12,5 +12,5 @@ module GrapePathHelpers
12
12
  require 'grape-path-helpers/railtie' if defined?(Rails)
13
13
  end
14
14
 
15
- Grape::API.extend GrapePathHelpers::AllRoutes
15
+ Grape::API::Instance.extend GrapePathHelpers::AllRoutes
16
16
  Grape::Endpoint.send(:include, GrapePathHelpers::NamedRouteMatcher)
@@ -11,7 +11,7 @@ module GrapePathHelpers
11
11
  end
12
12
 
13
13
  def all_routes
14
- routes = subclasses.flat_map { |s| s.send(:prepare_routes) }
14
+ routes = descendants.flat_map { |s| s.send(:prepare_routes) }
15
15
  routes.uniq { |r| r.options.merge(path: r.path) }
16
16
  end
17
17
  end
@@ -4,6 +4,9 @@ module GrapePathHelpers
4
4
  attr_reader :route, :helper_names, :helper_arguments,
5
5
  :extension, :route_options
6
6
 
7
+ PATH_SEGMENTS_REGEXP = %r{\(/?\.:?\w+\)|/(?!\))|(?<=\))|\??\*}
8
+ PATH_SEGMENTS_WITH_WILDCARDS_REGEXP = %r{\(/?\.:?\w+\)|/(?!\))|(?<=\))|\?}
9
+
7
10
  def self.sanitize_method_name(string)
8
11
  string.gsub(/\W|^[0-9]/, '_')
9
12
  end
@@ -40,12 +43,12 @@ module GrapePathHelpers
40
43
 
41
44
  def define_path_helper(method_name, route_attributes)
42
45
  method_body = <<-RUBY
43
- def #{method_name}(attributes = {})
46
+ def #{method_name}(attributes = {}, include_wildcard_segments = false)
44
47
  attrs = #{route_attributes}.merge(attributes)
45
48
 
46
49
  query_params = attrs.delete(:params)
47
50
  content_type = attrs.delete(:format)
48
- path = '/' + path_segments_with_values(attrs).join('/')
51
+ path = '/' + path_segments_with_values(attrs, include_wildcard_segments).join('/')
49
52
 
50
53
  path + content_type + query_string(query_params)
51
54
  end
@@ -99,13 +102,19 @@ module GrapePathHelpers
99
102
  end
100
103
  end
101
104
 
102
- def path_segments_with_values(opts)
103
- segments = path_segments.map { |s| segment_to_value(s, opts) }
105
+ def path_segments_with_values(opts, include_wildcard_segments = false)
106
+ segments = path_segments(include_wildcard_segments).map do |s|
107
+ segment_to_value(s, opts)
108
+ end
104
109
  segments.reject(&:blank?)
105
110
  end
106
111
 
107
- def path_segments
108
- pattern = %r{\(/?\.:?\w+\)|/(?!\))|(?<=\))|\??\*}
112
+ def path_segments(include_wildcard_segments = false)
113
+ pattern = if include_wildcard_segments
114
+ PATH_SEGMENTS_WITH_WILDCARDS_REGEXP
115
+ else
116
+ PATH_SEGMENTS_REGEXP
117
+ end
109
118
  route_path.split(pattern).reject(&:blank?)
110
119
  end
111
120
 
@@ -117,7 +126,7 @@ module GrapePathHelpers
117
126
  end
118
127
 
119
128
  def dynamic_segment?(segment)
120
- segment.start_with?(':')
129
+ segment.start_with?(':', '*')
121
130
  end
122
131
 
123
132
  def optional_segment?(segment)
@@ -3,26 +3,34 @@ module GrapePathHelpers
3
3
  # to unknown methods will look for a route with a matching
4
4
  # helper function name
5
5
  module NamedRouteMatcher
6
- def method_missing(method_id, *arguments)
6
+ def method_missing(method_id, *args, **kwargs)
7
7
  return super unless method_id.to_s =~ /_path$/
8
8
 
9
+ success, result = call_path_method(method_id, *args, **kwargs)
10
+
11
+ if success
12
+ result
13
+ else
14
+ super
15
+ end
16
+ end
17
+
18
+ def call_path_method(method_id, *arguments)
9
19
  segments = arguments.first || {}
10
20
 
11
- route = Grape::API.decorated_routes.detect do |r|
21
+ route = Grape::API::Instance.decorated_routes.detect do |r|
12
22
  route_match?(r, method_id, segments)
13
23
  end
14
24
 
15
- if route
16
- route.send(method_id, *arguments)
17
- else
18
- super
19
- end
25
+ return false unless route
26
+
27
+ [true, route.send(method_id, *arguments)]
20
28
  end
21
29
 
22
30
  def respond_to_missing?(method_name, _include_private = false)
23
31
  return super unless method_name =~ /_path$/
24
32
 
25
- Grape::API.decorated_routes.detect do |route|
33
+ Grape::API::Instance.decorated_routes.detect do |route|
26
34
  return true if route.respond_to?(method_name)
27
35
  end
28
36
 
@@ -3,7 +3,7 @@ module GrapePathHelpers
3
3
  # and required arguments for every Grape::Route.
4
4
  class RouteDisplayer
5
5
  def route_attributes
6
- Grape::API.decorated_routes.map do |route|
6
+ Grape::API::Instance.decorated_routes.map do |route|
7
7
  {
8
8
  route_path: route.route_path,
9
9
  route_method: route.route_method,
@@ -1,4 +1,4 @@
1
1
  # Gem version
2
2
  module GrapePathHelpers
3
- VERSION = '1.1.0'.freeze
3
+ VERSION = '1.6.0'.freeze
4
4
  end
@@ -1,7 +1,8 @@
1
1
  require 'spec_helper'
2
2
 
3
+ # rubocop:disable Metrics/BlockLength
3
4
  describe GrapePathHelpers::AllRoutes do
4
- Grape::API.extend described_class
5
+ Grape::API::Instance.extend described_class
5
6
 
6
7
  describe '#all_routes' do
7
8
  context 'when API is mounted within another API' do
@@ -11,7 +12,7 @@ describe GrapePathHelpers::AllRoutes do
11
12
  mounting_api
12
13
 
13
14
  # A route is unique if no other route shares the same set of options
14
- all_route_options = Grape::API.all_routes.map do |r|
15
+ all_route_options = Grape::API::Instance.all_routes.map do |r|
15
16
  r.instance_variable_get(:@options).merge(path: r.path)
16
17
  end
17
18
 
@@ -28,10 +29,18 @@ describe GrapePathHelpers::AllRoutes do
28
29
  it 'returns all POST routes' do
29
30
  expected_routes = Spec::Support::MultiplePostsAPI.routes.map(&:path)
30
31
 
31
- all_routes = Grape::API.all_routes
32
+ all_routes = Grape::API::Instance.all_routes
32
33
  expect(all_routes.map(&:path)).to include(*expected_routes)
33
34
  end
34
35
  end
36
+
37
+ context 'when an API is created via an intermediate class' do
38
+ it 'includes those routes on both Grape::API::Instance and the base class' do
39
+ expect(Spec::Support::BaseAPI.all_routes.map(&:origin)).to include('/derived_ping')
40
+ expect(Grape::API::Instance.all_routes.map(&:origin)).to include('/derived_ping')
41
+ end
42
+ end
35
43
  # rubocop:enable Metrics/LineLength
36
44
  end
37
45
  end
46
+ # rubocop:enable Metrics/BlockLength
@@ -19,7 +19,7 @@ describe GrapePathHelpers::DecoratedRoute do
19
19
  end
20
20
 
21
21
  let(:catch_all_route) do
22
- routes.detect { |route| route.route_path =~ /\*/ }
22
+ routes.detect { |route| route.route_path =~ /\*path/ }
23
23
  end
24
24
 
25
25
  let(:custom_route) do
@@ -34,6 +34,10 @@ describe GrapePathHelpers::DecoratedRoute do
34
34
  routes.detect { |route| route.route_path =~ /optional/ }
35
35
  end
36
36
 
37
+ let(:wildcard_route) do
38
+ routes.detect { |route| route.route_path =~ /\*owner_ids/ }
39
+ end
40
+
37
41
  describe '#sanitize_method_name' do
38
42
  it 'removes characters that are illegal in Ruby method names' do
39
43
  illegal_names = ['beta-1', 'name_with_+', 'name_with_(']
@@ -51,6 +55,53 @@ describe GrapePathHelpers::DecoratedRoute do
51
55
  end
52
56
  end
53
57
 
58
+ describe '#define_path_helper' do
59
+ context 'with only static segments' do
60
+ let(:route) { ping_route }
61
+
62
+ subject { route.api_v1_ping_path }
63
+
64
+ it { is_expected.to eq '/api/v1/ping.json' }
65
+ end
66
+
67
+ context 'with optional segments' do
68
+ let(:route) { optional_route }
69
+
70
+ subject { route.api_v1_cats______optional_path }
71
+
72
+ it { is_expected.to eq '/api/v1/cats/(-/)/optional.json' }
73
+ end
74
+
75
+ context 'with dynamic segments' do
76
+ let(:route) { show_route }
77
+
78
+ subject { route.api_v1_cats_path(id: 1) }
79
+
80
+ it { is_expected.to eq '/api/v1/cats/1.json' }
81
+ end
82
+
83
+ context 'with wildcard segments' do
84
+ let(:route) { wildcard_route }
85
+
86
+ context 'including them' do
87
+ subject do
88
+ route.api_v1_cats_owners_owner_ids_cats_path(
89
+ { owner_ids: 'foobar' },
90
+ true
91
+ )
92
+ end
93
+
94
+ it { is_expected.to eq '/api/v1/cats/owners/foobar/cats.json' }
95
+ end
96
+
97
+ context 'excluding them' do
98
+ subject { route.api_v1_cats_owners_owner_ids_cats_path }
99
+
100
+ it { is_expected.to eq '/api/v1/cats/owners/owner_ids/cats.json' }
101
+ end
102
+ end
103
+ end
104
+
54
105
  describe '#helper_names' do
55
106
  context 'when a route is given a custom helper name' do
56
107
  it 'uses the custom name instead of the dynamically generated one' do
@@ -119,7 +170,7 @@ describe GrapePathHelpers::DecoratedRoute do
119
170
 
120
171
  describe '#path_segments_with_values' do
121
172
  context 'when path has dynamic segments' do
122
- it 'replaces segments with corresponding values found in @options' do
173
+ it 'replaces segments with corresponding values found in options' do
123
174
  opts = { id: 1 }
124
175
  result = show_route.path_segments_with_values(opts)
125
176
  expect(result).to include(1)
@@ -133,6 +184,74 @@ describe GrapePathHelpers::DecoratedRoute do
133
184
  end
134
185
  end
135
186
  end
187
+
188
+ context 'when path has wildcard segments' do
189
+ context 'with regex excluding them' do
190
+ it "doesn't replaces wildcard segments" do
191
+ opts = { version: 4, id: 34, owner_ids: 'foobar' }
192
+
193
+ result = wildcard_route.path_segments_with_values(opts)
194
+ expect(result).to include(4)
195
+ expect(result).to include(34)
196
+ expect(result).to include('owner_ids')
197
+ expect(result).not_to include('foobar')
198
+ end
199
+
200
+ it "doesn't blank wildcard segments" do
201
+ opts = { version: 4, id: 34, owner_ids: '' }
202
+
203
+ result = wildcard_route.path_segments_with_values(opts)
204
+ expect(result).to include(4)
205
+ expect(result).to include(34)
206
+ expect(result).to include('owner_ids')
207
+ end
208
+ end
209
+
210
+ context 'with regex including them' do
211
+ context 'replaces segments' do
212
+ it 'with static text' do
213
+ opts = { version: 4, id: 34, owner_ids: 'foobar' }
214
+
215
+ result = wildcard_route.path_segments_with_values(opts, true)
216
+ expect(result).to include(4)
217
+ expect(result).to include(34)
218
+ expect(result).to include('foobar')
219
+ expect(result).not_to include('owner_ids')
220
+ end
221
+
222
+ it 'with additional segments' do
223
+ opts = { version: 4, id: 34, owner_ids: 'foo/bar/baz' }
224
+
225
+ result = wildcard_route.path_segments_with_values(opts, true)
226
+ expect(result).to include(4)
227
+ expect(result).to include(34)
228
+ expect(result).to include('foo/bar/baz')
229
+ expect(result).not_to include('owner_ids')
230
+ end
231
+ end
232
+
233
+ it 'blanks wildcard segments' do
234
+ opts = { version: 4, id: 34, owner_ids: '' }
235
+
236
+ result = wildcard_route.path_segments_with_values(opts, true)
237
+ expect(result).to include(4)
238
+ expect(result).to include(34)
239
+ expect(result).not_to include('owner_ids')
240
+ end
241
+
242
+ context 'when options contains string keys' do
243
+ it 'replaces segments' do
244
+ opts = { 'version' => 4, 'id' => 34, 'owner_ids' => 'foobar' }
245
+
246
+ result = wildcard_route.path_segments_with_values(opts, true)
247
+ expect(result).to include(4)
248
+ expect(result).to include(34)
249
+ expect(result).to include('foobar')
250
+ expect(result).not_to include('owner_ids')
251
+ end
252
+ end
253
+ end
254
+ end
136
255
  end
137
256
 
138
257
  describe '#path_helper_name' do
@@ -165,6 +284,13 @@ describe GrapePathHelpers::DecoratedRoute do
165
284
  expect(result).to eq('api_v1_path_path')
166
285
  end
167
286
  end
287
+
288
+ context 'when the path has a wildcard segment' do
289
+ it 'returns a name without the glob star' do
290
+ result = wildcard_route.path_helper_name
291
+ expect(result).to eq('api_v1_cats_owners_owner_ids_cats_path')
292
+ end
293
+ end
168
294
  end
169
295
 
170
296
  describe '#segment_to_value' do
@@ -5,7 +5,7 @@ describe GrapePathHelpers::NamedRouteMatcher do
5
5
  include described_class
6
6
 
7
7
  let(:routes) do
8
- Grape::API.decorated_routes
8
+ Grape::API::Instance.decorated_routes
9
9
  end
10
10
 
11
11
  let(:ping_route) do
@@ -30,8 +30,8 @@ describe GrapePathHelpers::NamedRouteMatcher do
30
30
  fake_class = Class.new do
31
31
  prepend GrapePathHelpers::NamedRouteMatcher
32
32
 
33
- def method_missing(_method_id, *_args)
34
- 'whatever' || super
33
+ def method_missing(method_id, *args, **kwargs)
34
+ [method_id, args, kwargs] || super
35
35
  end
36
36
 
37
37
  def respond_to_missing?(_method_name, _include_private = false)
@@ -44,13 +44,14 @@ describe GrapePathHelpers::NamedRouteMatcher do
44
44
 
45
45
  describe '#method_missing' do
46
46
  it 'returns super method_missing if the method does not end with path' do
47
- expect(Grape::API).not_to receive(:decorated_routes)
47
+ expect(Grape::API::Instance).not_to receive(:decorated_routes)
48
48
 
49
- helper_class.test_method
49
+ expect(helper_class.test_method(:arg1, kwarg1: :kwarg1))
50
+ .to eq([:test_method, [:arg1], { kwarg1: :kwarg1 }])
50
51
  end
51
52
 
52
53
  it 'search for the route if the method ends with path' do
53
- expect(Grape::API).to receive(:decorated_routes).and_call_original
54
+ expect(Grape::API::Instance).to receive(:decorated_routes).and_call_original # rubocop:disable Metrics/LineLength
54
55
 
55
56
  helper_class.test_method_path
56
57
  end
@@ -146,14 +147,14 @@ describe GrapePathHelpers::NamedRouteMatcher do
146
147
  end
147
148
 
148
149
  describe '#respond_to_missing?' do
149
- it 'returns super if the method doesb not end with path' do
150
- expect(Grape::API).not_to receive(:decorated_routes)
150
+ it 'returns super if the method does not end with path' do
151
+ expect(Grape::API::Instance).not_to receive(:decorated_routes) # rubocop:disable Metrics/LineLength
151
152
 
152
153
  expect(helper_class.send(:respond_to_missing?, :test)).to eq(false)
153
154
  end
154
155
 
155
156
  it 'search for the route if the method ends with path' do
156
- expect(Grape::API).to receive(:decorated_routes).and_call_original
157
+ expect(Grape::API::Instance).to receive(:decorated_routes).and_call_original # rubocop:disable Metrics/LineLength
157
158
 
158
159
  expect(helper_class.send(:respond_to_missing?, :test_path)).to eq(false)
159
160
  end
@@ -1,7 +1,7 @@
1
1
  module Spec
2
2
  module Support
3
3
  # Test API
4
- class API < Grape::API
4
+ class API < Grape::API::Instance
5
5
  version 'v1'
6
6
  prefix 'api'
7
7
  format 'json'
@@ -36,6 +36,10 @@ module Spec
36
36
  get ':id/owners/:owner_id' do
37
37
  'owner'
38
38
  end
39
+
40
+ get ':id/owners/*owner_ids/cats' do
41
+ %w[cats cats cats]
42
+ end
39
43
  end
40
44
 
41
45
  route :any, '*path' do
@@ -44,7 +48,7 @@ module Spec
44
48
  end
45
49
 
46
50
  # API with more than one version
47
- class APIWithMultipleVersions < Grape::API
51
+ class APIWithMultipleVersions < Grape::API::Instance
48
52
  version %w[beta alpha v1]
49
53
 
50
54
  get 'ping' do
@@ -53,13 +57,13 @@ module Spec
53
57
  end
54
58
 
55
59
  # API with another API mounted inside it
56
- class MountedAPI < Grape::API
60
+ class MountedAPI < Grape::API::Instance
57
61
  mount Spec::Support::API
58
62
  mount Spec::Support::APIWithMultipleVersions
59
63
  end
60
64
 
61
65
  # API with a version that would be illegal as a method name
62
- class APIWithIllegalVersion < Grape::API
66
+ class APIWithIllegalVersion < Grape::API::Instance
63
67
  version 'beta-1'
64
68
 
65
69
  get 'ping' do
@@ -68,7 +72,7 @@ module Spec
68
72
  end
69
73
 
70
74
  # API with multiple POST routes
71
- class MultiplePostsAPI < Grape::API
75
+ class MultiplePostsAPI < Grape::API::Instance
72
76
  resource :hamlet do
73
77
  post 'to_be' do
74
78
  end
@@ -77,5 +81,14 @@ module Spec
77
81
  end
78
82
  end
79
83
  end
84
+
85
+ class BaseAPI < Grape::API::Instance
86
+ end
87
+
88
+ class DerivedAPI < BaseAPI
89
+ get 'derived_ping' do
90
+ 'pong'
91
+ end
92
+ end
80
93
  end
81
94
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grape-path-helpers
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Drew Blessing
8
8
  - Harper Henn
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-12-17 00:00:00.000000000 Z
12
+ date: 2021-01-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -31,26 +31,26 @@ dependencies:
31
31
  requirements:
32
32
  - - "~>"
33
33
  - !ruby/object:Gem::Version
34
- version: '1.0'
34
+ version: '1.3'
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - "~>"
40
40
  - !ruby/object:Gem::Version
41
- version: '1.0'
41
+ version: '1.3'
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: rake
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
- - - "~>"
46
+ - - ">"
47
47
  - !ruby/object:Gem::Version
48
48
  version: '12'
49
49
  type: :runtime
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
- - - "~>"
53
+ - - ">"
54
54
  - !ruby/object:Gem::Version
55
55
  version: '12'
56
56
  - !ruby/object:Gem::Dependency
@@ -131,7 +131,7 @@ homepage: https://gitlab.com/gitlab-org/grape-path-helpers
131
131
  licenses:
132
132
  - MIT
133
133
  metadata: {}
134
- post_install_message:
134
+ post_install_message:
135
135
  rdoc_options: []
136
136
  require_paths:
137
137
  - lib
@@ -146,9 +146,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
146
146
  - !ruby/object:Gem::Version
147
147
  version: '0'
148
148
  requirements: []
149
- rubyforge_project:
150
- rubygems_version: 2.7.6
151
- signing_key:
149
+ rubygems_version: 3.2.3
150
+ signing_key:
152
151
  specification_version: 4
153
152
  summary: Route path helpers for Grape
154
153
  test_files: []