rutter 0.1.2 → 0.2.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.
@@ -2,22 +2,27 @@
2
2
 
3
3
  module Rutter
4
4
  RSpec.describe Routes do
5
- let(:router) { Builder.new }
5
+ let(:router) { Rutter.new }
6
6
  let(:routes) { Routes.new(router) }
7
+ let(:endpoint) { ->(_) {} }
7
8
 
8
9
  it "has a *_path helper method" do
9
- router.get "/books/:id", to: "Books#show", as: :book
10
- expect(routes.book_path(id: 54)).to eq("/books/54")
10
+ router.get "/books/:id", to: endpoint, as: :book
11
+
12
+ expect(routes.book_path(id: 54))
13
+ .to eq("/books/54")
11
14
  end
12
15
 
13
16
  it "has a *_url helper method" do
14
- router.get "/books/:id", to: "Books#show", as: :book
15
- expect(routes.book_url(id: 54)).to eq("http://example.com/books/54")
17
+ router.get "/books/:id", to: endpoint, as: :book
18
+
19
+ expect(routes.book_url(id: 54))
20
+ .to eq("http://localhost:9292/books/54")
16
21
  end
17
22
 
18
- it "raises ArgumentError if route not found" do
23
+ it "raises RuntimeError if route not found" do
19
24
  expect { routes.invalid_path }
20
- .to raise_error(ArgumentError)
25
+ .to raise_error(RuntimeError)
21
26
  end
22
27
 
23
28
  it "raises NoMethodError if unknown method is called" do
@@ -26,10 +31,14 @@ module Rutter
26
31
  end
27
32
 
28
33
  it "support respond_to?" do
29
- router.get "/books/:id", to: "Books#show", as: :book
30
- expect(routes.respond_to?(:book)).to eq(false)
31
- expect(routes.respond_to?(:book_path)).to eq(true)
32
- expect(routes.respond_to?(:book_url)).to eq(true)
34
+ router.get "/books/:id", to: endpoint, as: :book
35
+
36
+ expect(routes.respond_to?(:book))
37
+ .to eq(false)
38
+ expect(routes.respond_to?(:book_path))
39
+ .to eq(true)
40
+ expect(routes.respond_to?(:book_url))
41
+ .to eq(true)
33
42
  end
34
43
  end
35
44
  end
@@ -6,8 +6,9 @@ RSpec.describe Rutter do
6
6
  end
7
7
 
8
8
  describe ".new" do
9
- it "returns a new Builder object" do
10
- expect(Rutter.new).to be_a(Rutter::Builder)
9
+ it "creates a new builder object" do
10
+ expect(Rutter.new)
11
+ .to be_a(Rutter::Builder)
11
12
  end
12
13
  end
13
14
  end
@@ -1,75 +1,68 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rutter
4
- RSpec.describe Builder do
5
- let(:router) { Builder.new }
4
+ RSpec.describe Scope do
5
+ let(:router) { Rutter.new }
6
+ let(:endpoint) { ->(_) {} }
6
7
 
7
- describe "scope" do
8
- it "prepends prefixes" do
9
- router.scope path: "web", namespace: "Web" do
10
- get "/books", to: "Books#index"
8
+ it "support nested scopes" do
9
+ router.scope path: "animals", namespace: "species", as: :animals do
10
+ scope path: "mammals", namespace: "mammals", as: :mammals do
11
+ get "/cats", to: "cats#index", as: :cats
11
12
  end
12
-
13
- route = router.flat_map.first
14
-
15
- expect(route.path).to eq("/web/books")
16
- expect(route.endpoint[:controller]).to eq("Web::Books")
17
13
  end
18
14
 
19
- it "recognizes all verbs" do
20
- router.scope path: "/admin", namespace: "Secure", as: :koolaid do
21
- get "/", to: ->(env) {}
22
- post "/", to: ->(env) {}
23
- put "/", to: ->(env) {}
24
- patch "/", to: ->(env) {}
25
- delete "/", to: ->(env) {}
26
- options "/", to: ->(env) {}
27
- head "/", to: ->(env) {}
28
- trace "/", to: ->(env) {}
29
- end
15
+ route = router.flat_map.first
30
16
 
31
- expect(router.flat_map[0].method).to eq("GET")
32
- expect(router.flat_map[1].method).to eq("POST")
33
- expect(router.flat_map[2].method).to eq("PUT")
34
- expect(router.flat_map[3].method).to eq("PATCH")
35
- expect(router.flat_map[4].method).to eq("DELETE")
36
- expect(router.flat_map[5].method).to eq("OPTIONS")
37
- expect(router.flat_map[6].method).to eq("HEAD")
38
- expect(router.flat_map[7].method).to eq("TRACE")
39
- end
17
+ expect(route.path)
18
+ .to eq("/animals/mammals/cats")
19
+ expect(route.endpoint)
20
+ .to eq(controller: "Species::Mammals::Cats", action: "index")
21
+ expect(router.named_map[:animals_mammals_cats])
22
+ .to eq(route)
23
+ end
40
24
 
41
- describe "#root" do
42
- it "adds a root path with a root name" do
43
- router.scope path: "/admin", namespace: "Secure", as: :koolaid do
44
- root to: ->(env) {}
45
- end
25
+ describe "#add" do
26
+ it "support using route constraints" do
27
+ scope = router.scope path: "/books"
28
+ route = scope.get "/:id",
29
+ to: endpoint,
30
+ constraints: { id: /\d+/ }
46
31
 
47
- expect(router.flat_map.first.path).to eq("/admin")
48
- expect(router.named_map.key?(:koolaid_root)).to eq(true)
49
- end
32
+ expect(route.match?(env_for("/books/82")))
33
+ .to be(true)
34
+ expect(route.match?(env_for("/books/pickaxe")))
35
+ .to be(false)
50
36
  end
37
+ end
51
38
 
52
- it "support nested scopes" do
53
- router.scope path: "animals", namespace: "Species", as: :animals do
54
- scope path: "mammals", namespace: "Mammals", as: :mammals do
55
- get "/cats", to: "Cats#index", as: :cats
56
- end
57
- end
58
-
59
- route = router.flat_map.first
39
+ describe "#mount" do
40
+ it "matches path prefixes" do
41
+ scope = router.scope path: "/api"
42
+ route = scope.mount endpoint, at: "/v1"
60
43
 
61
- expect(route.path).to eq("/animals/mammals/cats")
62
- expect(route.endpoint[:controller]).to eq("Species::Mammals::Cats")
63
- expect(route.endpoint[:action]).to eq("index")
64
- expect(router.named_map.key?(:animals_mammals_cats)).to eq(true)
44
+ expect(route.match?(env_for("/")))
45
+ .to be_nil
46
+ expect(route.match?(env_for("/api")))
47
+ .to be_nil
48
+ expect(route.match?(env_for("/api/v1")))
49
+ .to eq("/api/v1")
50
+ expect(route.match?(env_for("/api/v1/books")))
51
+ .to eq("/api/v1")
65
52
  end
53
+ end
54
+
55
+ describe "verbs" do
56
+ let(:scope) { router.scope }
66
57
 
67
- describe "#mount" do
68
- it "calls the root mount with path prefix" do
69
- app = ->(_env) {}
58
+ VERBS.each do |verb|
59
+ describe "##{verb.downcase}" do
60
+ it "recognize #{verb} verb" do
61
+ route = scope.public_send verb.downcase, "/", to: endpoint
70
62
 
71
- expect(router).to receive(:mount).with(app, at: "/admin/books")
72
- router.scope(path: "/admin") { mount app, at: "books" }
63
+ expect(router.verb_map[verb])
64
+ .to eq([route])
65
+ end
73
66
  end
74
67
  end
75
68
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rutter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tobias Sandelius
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-03-05 00:00:00.000000000 Z
11
+ date: 2019-06-28 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: mustermann
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: rack
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -96,25 +110,21 @@ files:
96
110
  - README.md
97
111
  - Rakefile
98
112
  - bench/config.ru
99
- - bench/dynamic_routes
100
- - bench/expand
101
- - bench/helper.rb
102
- - bench/mount
103
- - bench/routes_helper
104
- - bench/static_routes
105
113
  - lib/rutter.rb
106
114
  - lib/rutter/builder.rb
115
+ - lib/rutter/mount.rb
116
+ - lib/rutter/naming.rb
107
117
  - lib/rutter/route.rb
108
118
  - lib/rutter/routes.rb
109
119
  - lib/rutter/scope.rb
120
+ - lib/rutter/verbs.rb
110
121
  - lib/rutter/version.rb
111
122
  - rutter.gemspec
112
- - spec/integration/mount_spec.rb
113
- - spec/integration/params_spec.rb
114
123
  - spec/integration/rack_spec.rb
115
- - spec/integration/redirect_spec.rb
116
124
  - spec/spec_helper.rb
125
+ - spec/support/rack.rb
117
126
  - spec/unit/builder_spec.rb
127
+ - spec/unit/namespace_spec.rb
118
128
  - spec/unit/route_spec.rb
119
129
  - spec/unit/routes_spec.rb
120
130
  - spec/unit/rutter_spec.rb
@@ -131,25 +141,23 @@ required_ruby_version: !ruby/object:Gem::Requirement
131
141
  requirements:
132
142
  - - ">="
133
143
  - !ruby/object:Gem::Version
134
- version: 2.4.0
144
+ version: 2.5.0
135
145
  required_rubygems_version: !ruby/object:Gem::Requirement
136
146
  requirements:
137
147
  - - ">="
138
148
  - !ruby/object:Gem::Version
139
149
  version: 2.5.0
140
150
  requirements: []
141
- rubyforge_project:
142
- rubygems_version: 2.6.13
151
+ rubygems_version: 3.0.3
143
152
  signing_key:
144
153
  specification_version: 4
145
154
  summary: HTTP router for Rack.
146
155
  test_files:
147
- - spec/integration/mount_spec.rb
148
- - spec/integration/params_spec.rb
149
156
  - spec/integration/rack_spec.rb
150
- - spec/integration/redirect_spec.rb
151
157
  - spec/spec_helper.rb
158
+ - spec/support/rack.rb
152
159
  - spec/unit/builder_spec.rb
160
+ - spec/unit/namespace_spec.rb
153
161
  - spec/unit/route_spec.rb
154
162
  - spec/unit/routes_spec.rb
155
163
  - spec/unit/rutter_spec.rb
data/bench/dynamic_routes DELETED
@@ -1,20 +0,0 @@
1
- #!/usr/bin/env ruby -W0
2
-
3
- require_relative "helper"
4
-
5
- router = Rutter.new
6
- app = Rack::MockRequest.new(router)
7
-
8
- Benchmark.bm(50) do |b|
9
- b.report "generating routes" do
10
- DICT.each do |route|
11
- router.get "#{route}/:id", to: $endpoint
12
- end
13
- end
14
-
15
- b.report "recognizing routes" do
16
- TIMES.times do
17
- app.get("#{DICT.sample}/54")
18
- end
19
- end
20
- end
data/bench/expand DELETED
@@ -1,19 +0,0 @@
1
- #!/usr/bin/env ruby -W0
2
-
3
- require_relative "helper"
4
-
5
- router = Rutter.new
6
-
7
- Benchmark.bm(50) do |b|
8
- b.report "generating routes" do
9
- DICT.each do |route|
10
- router.get "#{route}/:id", to: $endpoint, as: route
11
- end
12
- end
13
-
14
- b.report "expand routes" do
15
- TIMES.times do
16
- router.path(DICT.sample.to_sym, id: 54, key: "value")
17
- end
18
- end
19
- end
data/bench/helper.rb DELETED
@@ -1,19 +0,0 @@
1
- require "benchmark"
2
- require "rack"
3
- require_relative "../lib/rutter"
4
-
5
- BATCH_SIZE = 1000
6
- TIMES = 100000
7
- DICT = IO.foreach("/usr/share/dict/words")
8
- .lazy
9
- .map { |word| word.chomp.downcase }
10
- .uniq
11
- .take(BATCH_SIZE)
12
- .sort_by(&:length)
13
- .reverse
14
-
15
- $endpoint = ->(env) { [200, {}, ["Hello World"]] }
16
-
17
- puts "Loading #{BATCH_SIZE} routes, calling them #{TIMES} times...\n"
18
-
19
- GC.disable
data/bench/mount DELETED
@@ -1,32 +0,0 @@
1
- #!/usr/bin/env ruby -W0
2
-
3
- require_relative "helper"
4
-
5
- router = Rutter.new
6
- app = Rack::MockRequest.new(router)
7
-
8
- DICT.each do |route|
9
- router.mount $endpoint, at: route
10
- end
11
-
12
- builder = Rack::Builder.app do
13
- DICT.each do |route|
14
- map("/#{route}") { run $endpoint }
15
- end
16
- end
17
-
18
- rack_app = Rack::MockRequest.new(builder)
19
-
20
- Benchmark.bm(50) do |b|
21
- b.report "recognizing mounts" do
22
- TIMES.times do
23
- app.get("/#{DICT.sample}/sub/path")
24
- end
25
- end
26
-
27
- b.report "recognizing rack map" do
28
- TIMES.times do
29
- rack_app.get("/#{DICT.sample}/sub/path")
30
- end
31
- end
32
- end
data/bench/routes_helper DELETED
@@ -1,24 +0,0 @@
1
- #!/usr/bin/env ruby -W0
2
-
3
- require_relative "helper"
4
-
5
- router = Rutter.new
6
- routes = Rutter::Routes.new(router)
7
-
8
- DICT.each do |route|
9
- router.get "#{route}/:id", to: $endpoint, as: route
10
- end
11
-
12
- Benchmark.bm(50) do |b|
13
- b.report "dynamic *_path" do
14
- TIMES.times do
15
- routes.public_send "#{DICT.sample}_path", id: 54, key: "value"
16
- end
17
- end
18
-
19
- b.report "dynamic *_url" do
20
- TIMES.times do
21
- routes.public_send "#{DICT.sample}_url", id: 54, key: "value"
22
- end
23
- end
24
- end
data/bench/static_routes DELETED
@@ -1,20 +0,0 @@
1
- #!/usr/bin/env ruby -W0
2
-
3
- require_relative "helper"
4
-
5
- router = Rutter.new
6
- app = Rack::MockRequest.new(router)
7
-
8
- Benchmark.bm(50) do |b|
9
- b.report "generating routes" do
10
- DICT.each do |route|
11
- router.get route, to: $endpoint
12
- end
13
- end
14
-
15
- b.report "recognizing routes" do
16
- TIMES.times do
17
- app.get(DICT.sample)
18
- end
19
- end
20
- end
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe "Rutter::Builder#mount" do
4
- let(:router) do
5
- Rutter.new do
6
- mount ->(_env) { [200, {}, ["Admin App"]] }, at: "/admin"
7
- end
8
- end
9
-
10
- def app
11
- router.freeze
12
- end
13
-
14
- it "forwards the request to the given application" do
15
- get "/admin/with/sub/paths"
16
- expect(last_response.body).to eq("Admin App")
17
- end
18
- end