chespirito 0.0.2 → 0.0.3

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: 5d3588983bf384783e2066d7bb71175b0fafca6a17c35212526dbbc46f6a5209
4
- data.tar.gz: a9a8a41c4bbe2113112cc81428b302427861c5dafab63344a6bb54339a270384
3
+ metadata.gz: 8c4d6e5d80eb4af70ff671777425f063aa79ea43125e68c453ddb1be96f14abd
4
+ data.tar.gz: 0bb3fcbd997da246fa75b009517a8b53c8e57dffd2cd539db9c925179c5ba33f
5
5
  SHA512:
6
- metadata.gz: 85db7c0ac953324ed3c0102ec757af300384d1614a99446ed693f376444cf94dfa713ecca0a4cde330be3c0fd7cbc07628d542b571808e17434893fa6ece2a69
7
- data.tar.gz: 0bf474e6e562247c38126250bf53b799c66f18a1aeeee451a43c6c5190c83ecc6e0b6156215fea01576269e67f22e9b42d1aa453f189bb8c3751f68fd9ec487f
6
+ metadata.gz: ed1632d57adc92b16534f172e79de97003a3a97bb1698d330d0517de467722cb495993b563a9ae203f51000d2a58ccd8f64514a86b02d5a2d882effce6ea2852
7
+ data.tar.gz: 1f850630a40f3da4f642d30f3ce4ee0b81143889ecd47ee3cad57aa11b587cce30c6e8c119305f3e638403cbdfae6238739dd135b80295c2636381397a918beb
data/chespirito.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = 'chespirito'
5
- spec.version = '0.0.2'
5
+ spec.version = '0.0.3'
6
6
  spec.summary = 'Chespirito Ruby web framework'
7
7
  spec.description = 'A dead simple, yet Rack-compatible, web framework written in Ruby'
8
8
  spec.authors = ['Leandro Proença']
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative './request'
4
- require_relative './router'
4
+ require_relative './routes/router'
5
5
 
6
6
  module Chespirito
7
7
  class App
@@ -15,17 +15,19 @@ module Chespirito
15
15
  new.tap { |app| yield(app) }
16
16
  end
17
17
 
18
- def register_route(*attrs)
19
- attrs => [verb, path, trait]
20
-
18
+ def register_route(verb, path, trait)
21
19
  @router.register_route(verb, path, trait)
22
20
  end
23
21
 
24
- def lookup(request) = @router.lookup(request)
22
+ def register_system_route(key, trait)
23
+ @router.register_system_route(key, trait)
24
+ end
25
+
26
+ def dispatch(request) = @router.dispatch(request)
25
27
 
26
28
  def call(env)
27
29
  request = ::Chespirito::Request.build(env)
28
- response = lookup(request)
30
+ response = dispatch(request)
29
31
 
30
32
  [
31
33
  response.status,
@@ -11,7 +11,7 @@ module Chespirito
11
11
  @response = ::Chespirito::Response.new
12
12
  end
13
13
 
14
- def self.dispatch(action, request)
14
+ def self.process(action, request)
15
15
  new(request)
16
16
  .tap { |controller| controller.send(action.to_sym) }
17
17
  .then { |controller| controller.response }
@@ -30,5 +30,11 @@ module Chespirito
30
30
  cookies: rack_request.cookies
31
31
  )
32
32
  end
33
+
34
+ def add_param!(name, value)
35
+ @params ||= {}
36
+
37
+ @params[name] = value
38
+ end
33
39
  end
34
40
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chespirito
4
+ class Route
5
+ attr_reader :verb, :path, :controller_klass, :action
6
+
7
+ def initialize(*attrs)
8
+ @verb, @path, @trait = attrs
9
+ @controller_klass, @action = @trait
10
+ end
11
+
12
+ def key = "#{@verb} #{@path}"
13
+ end
14
+
15
+ class SystemRoute
16
+ attr_reader :key, :controller_klass, :action
17
+
18
+ def initialize(*attrs)
19
+ @key, @trait = attrs
20
+ @controller_klass, @action = @trait
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './route_utils'
4
+
5
+ module Chespirito
6
+ class RouteConstraintChecker
7
+ def initialize(request)
8
+ @request = request
9
+ end
10
+
11
+ def match_route?(route)
12
+ return false unless route.respond_to?(:path)
13
+ return false if route_constraints(route).empty?
14
+
15
+ route_constraints(route).size == request_constraints(route).size
16
+ end
17
+
18
+ def extract_params(route)
19
+ return {} unless route.respond_to?(:path)
20
+ return {} unless match_route?(route)
21
+
22
+ route_constraints(route)
23
+ .zip(request_constraints(route))
24
+ .to_h
25
+ end
26
+
27
+ def route_constraints(route) = RouteUtils.constraints(route.path)
28
+ def request_constraints(route) = request_parts - route_parts(route)
29
+
30
+ def route_parts(route) = RouteUtils.parts(route.path)
31
+ def request_parts = RouteUtils.words(@request.path)
32
+ end
33
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chespirito
4
+ class RouteUtils
5
+ class << self
6
+ def words(path) = path.split("/").delete_if(&:empty?)
7
+ def constraints(path) = words(path).select(&method(:constraint?)).map(&method(:remove_colon))
8
+ def parts(path) = words(path).select(&method(:part?))
9
+ def part?(word) = !constraint?(word)
10
+ def constraint?(word) = word.start_with?(":")
11
+ def remove_colon(word) = word.gsub(":", '')
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './route'
4
+ require_relative './route_constraint_checker'
5
+ require_relative '../response'
6
+
7
+ module Chespirito
8
+ class Router
9
+ def initialize
10
+ @routes = {}
11
+ end
12
+
13
+ def register_route(*attrs)
14
+ route = Route.new(*attrs)
15
+
16
+ @routes[route.key] = route
17
+ end
18
+
19
+ def register_system_route(*attrs)
20
+ route = SystemRoute.new(*attrs)
21
+
22
+ @routes[route.key] = route
23
+ end
24
+
25
+ def dispatch(request)
26
+ route = route_for(request)
27
+ return not_found_response unless route
28
+
29
+ route
30
+ .controller_klass
31
+ .process(route.action, request)
32
+ end
33
+
34
+ def route_for(request)
35
+ simple_route(request) || constraint_route(request) || not_found_route
36
+ end
37
+
38
+ def simple_route(request)
39
+ @routes["#{request.verb} #{request.path}"]
40
+ end
41
+
42
+ def constraint_route(request)
43
+ constraint_checker = RouteConstraintChecker.new(request)
44
+
45
+ route = @routes.values.find(&constraint_checker.method(:match_route?))
46
+ return unless route
47
+
48
+ route.tap do
49
+ constraint_checker
50
+ .extract_params(route)
51
+ .each { |(name, value)| request.add_param!(name, value) }
52
+ end
53
+ end
54
+
55
+ def not_found_route = @routes['404'] || @routes[:not_found]
56
+
57
+ def not_found_response
58
+ ::Chespirito::Response.new.tap do |response|
59
+ response.status = 404
60
+ response.headers = {}
61
+ response.body = ''
62
+ end
63
+ end
64
+ end
65
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chespirito
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Leandro Proença
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-05-23 00:00:00.000000000 Z
11
+ date: 2022-05-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -53,7 +53,10 @@ files:
53
53
  - lib/chespirito/controller.rb
54
54
  - lib/chespirito/request.rb
55
55
  - lib/chespirito/response.rb
56
- - lib/chespirito/router.rb
56
+ - lib/chespirito/routes/route.rb
57
+ - lib/chespirito/routes/route_constraint_checker.rb
58
+ - lib/chespirito/routes/route_utils.rb
59
+ - lib/chespirito/routes/router.rb
57
60
  homepage: https://github.com/leandronsp/chespirito
58
61
  licenses:
59
62
  - MIT
@@ -1,34 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative './request'
4
- require_relative './response'
5
-
6
- module Chespirito
7
- class Router
8
- def initialize
9
- @routes = {}
10
- end
11
-
12
- def register_route(verb, path, trait)
13
- @routes[route_key(verb, path)] = trait
14
- end
15
-
16
- def lookup(request)
17
- controller_klass, action = @routes[route_key(request.verb, request.path)]
18
-
19
- return not_found_response unless controller_klass
20
-
21
- controller_klass.dispatch(action, request)
22
- end
23
-
24
- def route_key(verb, path) = "#{verb} #{path}"
25
-
26
- def not_found_response
27
- ::Chespirito::Response.new.tap do |response|
28
- response.status = 404
29
- response.headers = {}
30
- response.body = ''
31
- end
32
- end
33
- end
34
- end