hanami-router 2.2.0.rc1 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6dbd5cec52e1e7a0d2ac82066294bf3846b58b4c8bacd3555d6f0f1a3e6cb873
4
- data.tar.gz: e96f0ff6c694e0964325d012f18c055a892af912e5f6dd3ba35f0bec13173fa0
3
+ metadata.gz: 5bba2b56b3f4ddbedc47b2d21189f7e88ce172505dabbdca6c6d6266aa6c7fa2
4
+ data.tar.gz: d601d610fb2cacbef79ca4770ab1e63869a5469ac46671c823e106086c0e58d0
5
5
  SHA512:
6
- metadata.gz: 8dc08ace41fd84808b9706c2a4d07de0c45f3c206eb858020e8fa7970005e6eeefb721a8654bd86379d8389c71d813b9406ffb4c47eecde4c97558baf6eff3e2
7
- data.tar.gz: e28b53acd76af8d279ca365cfa8c9901ce5fc5d789736eef5cd7925e9ecb89845e58caaa9548ebefe2050b792a7704880c84bb2b27adf27c0c6df288b5bd3969
6
+ metadata.gz: 88b44cc6c09c227aaf45352a49344a48530c4095fa1ac2f53ed0bf38e7901876805121c1090d24759420c8ad0029fbc9aba43d383adb93635161ce3cfb8fe321
7
+ data.tar.gz: 319831eb561257e58afbc2479447e92862b452424a44c1efffc8f534d4bfc40f2549e70d0849ef4e303182f7d8ec620ad8a6d55a25f9e3994a20215c3dd89bf8
data/CHANGELOG.md CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  Rack compatible HTTP router for Ruby
4
4
 
5
+ ## v2.2.0 - 2024-11-05
6
+
7
+ ### Changed
8
+
9
+ - [Damian C. Rossney, Kyle Plump] Scopes with a dynamic segment (e.g. `scope ":locale" do`) and containing a `root` route will no longer match the root route for requests with a trailing slash. This makes the behavior consistent with scopes using static strings. (#273)
10
+
11
+ ### Fixed
12
+
13
+ - [Damian C. Rossney, Kyle Plump] Support paths with different variable names in same path location (#273)
14
+
5
15
  ## v2.2.0.rc1 - 2024-10-29
6
16
 
7
17
  ## v2.2.0.beta2 - 2024-09-25
@@ -37,7 +37,7 @@ module Hanami
37
37
  # @api private
38
38
  # @since 2.0.0
39
39
  def call(routes, **csv_opts)
40
- ::CSV.generate(**DEFAULT_OPTIONS.merge(csv_opts)) do |csv|
40
+ ::CSV.generate(**DEFAULT_OPTIONS, **csv_opts) do |csv|
41
41
  csv << HEADERS if csv.write_headers?
42
42
  routes.reduce(csv) do |acc, route|
43
43
  route.head? ? acc : acc << row(route)
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "mustermann/rails"
4
+
5
+ module Hanami
6
+ class Router
7
+ class Leaf
8
+ # Trie Leaf
9
+ #
10
+ # @api private
11
+ # @since 2.2.0
12
+ attr_reader :to, :params
13
+
14
+ # @api private
15
+ # @since 2.2.0
16
+ def initialize(route, to, constraints)
17
+ @route = route
18
+ @to = to
19
+ @constraints = constraints
20
+ @params = nil
21
+ end
22
+
23
+ # @api private
24
+ # @since 2.2.0
25
+ def match(path)
26
+ match = matcher.match(path)
27
+
28
+ @params = match.named_captures if match
29
+
30
+ match
31
+ end
32
+
33
+ private
34
+
35
+ # @api private
36
+ # @since 2.2.0
37
+ def matcher
38
+ @matcher ||= Mustermann.new(@route, type: :rails, version: "5.0", capture: @constraints)
39
+ end
40
+ end
41
+ end
42
+ end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "hanami/router/segment"
3
+ require "hanami/router/leaf"
4
4
 
5
5
  module Hanami
6
6
  class Router
@@ -18,15 +18,14 @@ module Hanami
18
18
  def initialize
19
19
  @variable = nil
20
20
  @fixed = nil
21
- @to = nil
21
+ @leaves = nil
22
22
  end
23
23
 
24
24
  # @api private
25
25
  # @since 2.0.0
26
- def put(segment, constraints)
26
+ def put(segment)
27
27
  if variable?(segment)
28
- @variable ||= {}
29
- @variable[segment_for(segment, constraints)] ||= self.class.new
28
+ @variable ||= self.class.new
30
29
  else
31
30
  @fixed ||= {}
32
31
  @fixed[segment] ||= self.class.new
@@ -35,36 +34,21 @@ module Hanami
35
34
 
36
35
  # @api private
37
36
  # @since 2.0.0
38
- #
39
- def get(segment) # rubocop:disable Metrics/PerceivedComplexity
40
- return unless @variable || @fixed
41
-
42
- found = nil
43
- captured = nil
44
-
45
- found = @fixed&.fetch(segment, nil)
46
- return [found, nil] if found
47
-
48
- @variable&.each do |matcher, node|
49
- break if found
50
-
51
- captured = matcher.match(segment)
52
- found = node if captured
53
- end
54
-
55
- [found, captured&.named_captures]
37
+ def get(segment)
38
+ @fixed&.fetch(segment, nil) || @variable
56
39
  end
57
40
 
58
41
  # @api private
59
42
  # @since 2.0.0
60
- def leaf?
61
- @to
43
+ def leaf!(route, to, constraints)
44
+ @leaves ||= []
45
+ @leaves << Leaf.new(route, to, constraints)
62
46
  end
63
47
 
64
48
  # @api private
65
- # @since 2.0.0
66
- def leaf!(to)
67
- @to = to
49
+ # @since 2.2.0
50
+ def match(path)
51
+ @leaves&.find { |leaf| leaf.match(path) }
68
52
  end
69
53
 
70
54
  private
@@ -74,18 +58,6 @@ module Hanami
74
58
  def variable?(segment)
75
59
  Router::ROUTE_VARIABLE_MATCHER.match?(segment)
76
60
  end
77
-
78
- # @api private
79
- # @since 2.0.0
80
- def segment_for(segment, constraints)
81
- Segment.fabricate(segment, **constraints)
82
- end
83
-
84
- # @api private
85
- # @since 2.0.0
86
- def fixed?(matcher)
87
- matcher.names.empty?
88
- end
89
61
  end
90
62
  end
91
63
  end
@@ -21,33 +21,26 @@ module Hanami
21
21
 
22
22
  # @api private
23
23
  # @since 2.0.0
24
- def add(path, to, constraints)
24
+ def add(route, to, constraints)
25
+ segments = segments_from(route)
25
26
  node = @root
26
- for_each_segment(path) do |segment|
27
- node = node.put(segment, constraints)
27
+
28
+ segments.each do |segment|
29
+ node = node.put(segment)
28
30
  end
29
31
 
30
- node.leaf!(to)
32
+ node.leaf!(route, to, constraints)
31
33
  end
32
34
 
33
35
  # @api private
34
36
  # @since 2.0.0
35
37
  def find(path)
38
+ segments = segments_from(path)
36
39
  node = @root
37
- params = {}
38
-
39
- for_each_segment(path) do |segment|
40
- break unless node
41
40
 
42
- child, captures = node.get(segment)
43
- params.merge!(captures) if captures
44
-
45
- node = child
46
- end
41
+ return unless segments.all? { |segment| node = node.get(segment) }
47
42
 
48
- return [node.to, params] if node&.leaf?
49
-
50
- nil
43
+ node.match(path)&.then { |found| [found.to, found.params] }
51
44
  end
52
45
 
53
46
  private
@@ -58,10 +51,11 @@ module Hanami
58
51
  private_constant :SEGMENT_SEPARATOR
59
52
 
60
53
  # @api private
61
- # @since 2.0.0
62
- def for_each_segment(path, &blk)
54
+ # @since 2.2.0
55
+ def segments_from(path)
63
56
  _, *segments = path.split(SEGMENT_SEPARATOR)
64
- segments.each(&blk)
57
+
58
+ segments
65
59
  end
66
60
  end
67
61
  end
@@ -8,6 +8,6 @@ module Hanami
8
8
  #
9
9
  # @since 0.1.0
10
10
  # @api public
11
- VERSION = "2.2.0.rc1"
11
+ VERSION = "2.2.0"
12
12
  end
13
13
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hanami-router
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0.rc1
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luca Guidi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-10-29 00:00:00.000000000 Z
11
+ date: 2024-11-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -171,6 +171,7 @@ files:
171
171
  - lib/hanami/router/formatter/human_friendly.rb
172
172
  - lib/hanami/router/globbed_path.rb
173
173
  - lib/hanami/router/inspector.rb
174
+ - lib/hanami/router/leaf.rb
174
175
  - lib/hanami/router/mounted_path.rb
175
176
  - lib/hanami/router/node.rb
176
177
  - lib/hanami/router/params.rb