Skip to content

Commit 981258e

Browse files
feat: add support for multiple patterns with same arguments (#1216)
1 parent 7fa9eec commit 981258e

File tree

22 files changed

+2357
-2
lines changed

22 files changed

+2357
-2
lines changed

gapic-generator/lib/gapic/presenters/resource_presenter.rb

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,13 @@ class ResourcePresenter
2626
def initialize resource
2727
@resource = resource
2828

29-
@patterns = resource.pattern.map { |pattern| PatternPresenter.new pattern }
29+
all_patterns = resource.pattern.map { |pattern| PatternPresenter.new pattern }
3030

3131
# Keep only patterns that can be used to create path helpers
32-
@patterns.filter!(&:useful_for_helpers?)
32+
all_useful_patterns = all_patterns.filter(&:useful_for_helpers?)
33+
34+
# Remove patterns where key is duplicated
35+
@patterns = ResourcePresenter.dedup_patterns all_useful_patterns
3336
end
3437

3538
def dup
@@ -52,6 +55,25 @@ def path_helper
5255
"#{ActiveSupport::Inflector.underscore name}_path"
5356
end
5457

58+
##
59+
# Deduplicates pattern that have the same `arguments_key`. Our design for the "paths" helper
60+
# only allows for one pattern per `arguments_key`.
61+
#
62+
# If patterns with the same `arguments_key` are detected, the shortest is taken. If there is
63+
# a tie, the lexicographically first is taken.
64+
#
65+
# @param patterns [Array<PatternPresenter>]
66+
#
67+
# @return [Array<PatternPresenter>]
68+
#
69+
def self.dedup_patterns patterns
70+
patterns.group_by(&:arguments_key).map do |_arguments_key, group|
71+
group.min_by do |pattern|
72+
[pattern.pattern.length, pattern.pattern]
73+
end
74+
end
75+
end
76+
5577
##
5678
# A presenter for a particular pattern
5779
#
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# frozen_string_literal: true
2+
3+
# Copyright 2025 Google LLC
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# https://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
require "test_helper"
18+
require "gapic/presenters/resource_presenter"
19+
20+
class ResourcePresenterTest < PresenterTest
21+
def test_noargument_nodedup
22+
patterns = [
23+
"hello/compatibility/world"
24+
].map { |pattern| Gapic::Presenters::ResourcePresenter::PatternPresenter.new pattern }
25+
26+
deduped_patterns = Gapic::Presenters::ResourcePresenter.dedup_patterns(patterns).map(&:pattern)
27+
28+
assert_equal ["hello/compatibility/world"], deduped_patterns
29+
end
30+
31+
def test_noargument_dedup
32+
patterns = [
33+
"hello/world",
34+
"hello/zorld",
35+
"hello/compatibility/world"
36+
].map { |pattern| Gapic::Presenters::ResourcePresenter::PatternPresenter.new pattern }
37+
38+
deduped_patterns = Gapic::Presenters::ResourcePresenter.dedup_patterns(patterns).map(&:pattern)
39+
40+
assert_equal ["hello/world"], deduped_patterns
41+
end
42+
43+
def test_noargument_dedup_with_additional
44+
patterns = [
45+
"hello/world",
46+
"hello/compatibility/world",
47+
"hello/{foo}/world/{world}"
48+
].map { |pattern| Gapic::Presenters::ResourcePresenter::PatternPresenter.new pattern }
49+
50+
deduped_patterns = Gapic::Presenters::ResourcePresenter.dedup_patterns(patterns).map(&:pattern)
51+
52+
assert_equal ["hello/world", "hello/{foo}/world/{world}"], deduped_patterns
53+
end
54+
55+
def test_argument_nodedup
56+
patterns = [
57+
"hello/{foo}/world/{world}"
58+
].map { |pattern| Gapic::Presenters::ResourcePresenter::PatternPresenter.new pattern }
59+
60+
deduped_patterns = Gapic::Presenters::ResourcePresenter.dedup_patterns(patterns).map(&:pattern)
61+
62+
assert_equal ["hello/{foo}/world/{world}"], deduped_patterns
63+
end
64+
65+
def test_argument_dedup
66+
patterns = [
67+
"hello/{foo}/world/{world}",
68+
"hello/{foo}/compatibility/world/{world}",
69+
"hello/{foo}/zorld/{world}"
70+
].map { |pattern| Gapic::Presenters::ResourcePresenter::PatternPresenter.new pattern }
71+
72+
deduped_patterns = Gapic::Presenters::ResourcePresenter.dedup_patterns(patterns).map(&:pattern)
73+
74+
assert_equal ["hello/{foo}/world/{world}"], deduped_patterns
75+
end
76+
77+
def test_argument_dedup_with_additional
78+
patterns = [
79+
"hello/{foo}/world/{world}",
80+
"hello/{foo}/compatibility/world/{world}",
81+
"baz/{baz}"
82+
].map { |pattern| Gapic::Presenters::ResourcePresenter::PatternPresenter.new pattern }
83+
84+
deduped_patterns = Gapic::Presenters::ResourcePresenter.dedup_patterns(patterns).map(&:pattern)
85+
86+
assert_equal ["hello/{foo}/world/{world}", "baz/{baz}"], deduped_patterns
87+
end
88+
end

shared/gem_defaults.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ def gem_defaults
155155
"testing/grpc_service_config/grpc_service_config.proto",
156156
"testing/mixins/mixins.proto",
157157
"testing/routing_headers/routing_headers.proto",
158+
"testing/resources/resources.proto",
158159
"testing/nonstandard_lro_grpc/nonstandard_lro_grpc.proto",
159160
# `locations.proto` is included here because it is often
160161
# included in the real world libraries

shared/input/testing_desc.bin

14.2 KB
Binary file not shown.

shared/output/gapic/templates/testing/lib/testing.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,5 @@
2929
# require "testing/grpc_service_config"
3030
# require "testing/mixins"
3131
# require "testing/nonstandard_lro_grpc"
32+
# require "testing/resources"
3233
# require "testing/routing_headers"
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# frozen_string_literal: true
2+
3+
# The MIT License (MIT)
4+
#
5+
# Copyright <YEAR> <COPYRIGHT HOLDER>
6+
#
7+
# Permission is hereby granted, free of charge, to any person obtaining a copy
8+
# of this software and associated documentation files (the "Software"), to deal
9+
# in the Software without restriction, including without limitation the rights
10+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
# copies of the Software, and to permit persons to whom the Software is
12+
# furnished to do so, subject to the following conditions:
13+
#
14+
# The above copyright notice and this permission notice shall be included in
15+
# all copies or substantial portions of the Software.
16+
#
17+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
# THE SOFTWARE.
24+
25+
# Auto-generated by gapic-generator-ruby. DO NOT EDIT!
26+
27+
require "testing/resources/service_resources"
28+
require "testing/version"
29+
30+
module Testing
31+
##
32+
# API client module.
33+
#
34+
# @example Load this package, including all its services, and instantiate a gRPC client
35+
#
36+
# require "testing/resources"
37+
# client = ::Testing::Resources::ServiceResources::Client.new
38+
#
39+
module Resources
40+
end
41+
end
42+
43+
helper_path = ::File.join __dir__, "resources", "_helpers.rb"
44+
require "testing/resources/_helpers" if ::File.file? helper_path

shared/output/gapic/templates/testing/lib/testing/resources/resources_pb.rb

Lines changed: 45 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

shared/output/gapic/templates/testing/lib/testing/resources/resources_services_pb.rb

Lines changed: 27 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# frozen_string_literal: true
2+
3+
# The MIT License (MIT)
4+
#
5+
# Copyright <YEAR> <COPYRIGHT HOLDER>
6+
#
7+
# Permission is hereby granted, free of charge, to any person obtaining a copy
8+
# of this software and associated documentation files (the "Software"), to deal
9+
# in the Software without restriction, including without limitation the rights
10+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
# copies of the Software, and to permit persons to whom the Software is
12+
# furnished to do so, subject to the following conditions:
13+
#
14+
# The above copyright notice and this permission notice shall be included in
15+
# all copies or substantial portions of the Software.
16+
#
17+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
# THE SOFTWARE.
24+
25+
# Auto-generated by gapic-generator-ruby. DO NOT EDIT!
26+
27+
require "gapic/common"
28+
require "gapic/config"
29+
require "gapic/config/method"
30+
31+
require "testing/version"
32+
33+
require "testing/resources/service_resources/credentials"
34+
require "testing/resources/service_resources/paths"
35+
require "testing/resources/service_resources/client"
36+
37+
module Testing
38+
module Resources
39+
##
40+
# @example Load this service and instantiate a gRPC client
41+
#
42+
# require "testing/resources/service_resources"
43+
# client = ::Testing::Resources::ServiceResources::Client.new
44+
#
45+
module ServiceResources
46+
end
47+
end
48+
end
49+
50+
helper_path = ::File.join __dir__, "service_resources", "helpers.rb"
51+
require "testing/resources/service_resources/helpers" if ::File.file? helper_path

0 commit comments

Comments
 (0)