rack-way 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: aec7c90f616cb7808ded767c3a85aa7c5859c127711769f5769a1251a2aa751d
4
- data.tar.gz: 52c386fb62e85c43c7f1ef9a9d236c1736984fcaf89f041f3e521c3c6249750e
3
+ metadata.gz: a49ebbc6df20d07f91d19e38ee194c6a2958d397c357b8ab6b262ba7ed256902
4
+ data.tar.gz: ef3a7824645ef0bea5b2f06a4ea3ca89c5cd5eb5daeea2e1f0028dcbee60676a
5
5
  SHA512:
6
- metadata.gz: a920776a352b76981d86da5df95e48fdbd1017ec0a436e1c56e6d4205634fb4c9ebb0427766ef69645157d6d7f63c825345b54cb4efc3c26916604c27f16cb45
7
- data.tar.gz: 70db0b57ac30337cccdc261d52129dc08dd151f1bb0b4159ccd29b2fadee3e4967eb5fca25d094e652fd400f320318f22e69d706c645e41ddeedcfc4339cea5e
6
+ metadata.gz: 48802c9548cbdeb967d28dc8a0d543841bcbc0fbb4fc6bdbe9976260df76795060abcc8dce9de3a500aea2dbba0bcdbd5ff55c5c30bc9df2afa65ea28e62049c
7
+ data.tar.gz: 50e8fb5a03bfdefaa88b5d3b0fabb73bb587b4c2e6c47fe01d787bd4e0898e80bb84e078a61938b0dd169e8ec650c4bbfa99c5e416724dc24f174440eb4b8a21
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'erubi'
2
4
  require 'json'
3
5
  require 'rack'
@@ -5,6 +7,34 @@ require 'rack'
5
7
  module Rack
6
8
  class Way
7
9
  module Action
10
+ def self.included(base)
11
+ base.class_eval do
12
+ attr_reader :route if self != Rack::Way
13
+
14
+ def initialize(route)
15
+ @route = route
16
+ end
17
+
18
+ def view_response(a_path, a_view_params = {}, status: 200)
19
+ Rack::Way::Action.view_response(
20
+ a_path,
21
+ a_view_params,
22
+ status: status, route: route
23
+ )
24
+ end
25
+
26
+ def view(
27
+ a_path, a_view_params = {}, status: 200, response_instance: false
28
+ )
29
+ Rack::Way::Action.view(
30
+ a_path,
31
+ a_view_params,
32
+ status: status, response_instance: response_instance, route: route
33
+ )
34
+ end
35
+ end
36
+ end
37
+
8
38
  def html(content, status: 200)
9
39
  Rack::Way::Action.html(content, status: status)
10
40
  end
@@ -13,14 +43,6 @@ module Rack
13
43
  Rack::Way::Action.html_response(content, status: status)
14
44
  end
15
45
 
16
- def view_response(path, view_params = {}, status: 200)
17
- Rack::Way::Action.view_response(path, view_params, status: status)
18
- end
19
-
20
- def view(path, view_params = {}, status: 200, response_instance: false)
21
- Rack::Way::Action.view(path, view_params, status: status, response_instance: response_instance)
22
- end
23
-
24
46
  def json(content = {}, status: 200)
25
47
  Rack::Way::Action.json(content, status: status)
26
48
  end
@@ -58,16 +80,27 @@ module Rack
58
80
  Rack::Response.new(content, status, { 'Content-Type' => 'text/html' })
59
81
  end
60
82
 
61
- def view_response(paths, view_params = {}, status: 200)
62
- view(paths, view_params, status: status, response_instance: true)
83
+ def view_response(paths, view_params = {}, status: 200, route: nil)
84
+ view(
85
+ paths,
86
+ view_params,
87
+ status: status, response_instance: true,
88
+ route: route
89
+ )
63
90
  end
64
91
 
65
- def view(paths, view_params = {}, status: 200, response_instance: false)
66
- if paths.kind_of?(Array)
67
- erb = paths.map { |path| erb("views/#{path}", view_params) }.join
68
- else
69
- erb = erb("views/#{paths}", view_params)
70
- end
92
+ def view(
93
+ paths,
94
+ view_params = {},
95
+ status: 200,
96
+ response_instance: false,
97
+ route: nil
98
+ )
99
+ erb = if paths.is_a?(Array)
100
+ paths.map { |path| erb("views/#{path}", route, view_params) }.join
101
+ else
102
+ erb("views/#{paths}", route, view_params)
103
+ end
71
104
 
72
105
  if response_instance
73
106
  return Rack::Response.new(
@@ -104,7 +137,7 @@ module Rack
104
137
  )
105
138
  end
106
139
 
107
- def erb(path, view_params = {})
140
+ def erb(path, _route, view_params = {})
108
141
  @view = OpenStruct.new(view_params)
109
142
 
110
143
  eval(Erubi::Engine.new(::File.read("#{path}.html.erb")).src)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rack
2
4
  class Way
3
5
  class Router
@@ -10,7 +12,7 @@ module Rack
10
12
  request = Rack::Request.new(@env)
11
13
 
12
14
  return request if route.nil?
13
- return request unless route.has_params?
15
+ return request unless route.has_params
14
16
 
15
17
  update_request_params(request, route)
16
18
  end
@@ -1,26 +1,25 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rack
2
4
  class Way
3
5
  class Router
4
6
  class Route
5
- attr_reader :endpoint, :splitted_path
7
+ attr_reader :endpoint, :splitted_path, :has_params
6
8
 
7
9
  def initialize(path, endpoint)
8
10
  @path = path
9
11
  @splitted_path = @path.split('/')
10
12
  @endpoint = endpoint
11
13
  @params = fetch_params
14
+ @has_params = @params != []
12
15
  end
13
16
 
14
17
  def match?(env)
15
- return match_with_params?(env) if has_params?
18
+ return match_with_params?(env) if @has_params
16
19
 
17
20
  env['REQUEST_PATH'] == @path
18
21
  end
19
22
 
20
- def has_params?
21
- @params != []
22
- end
23
-
24
23
  private
25
24
 
26
25
  def fetch_params
@@ -30,20 +29,18 @@ module Rack
30
29
  def match_with_params?(env)
31
30
  splitted_request_path = env['REQUEST_PATH'].split('/')
32
31
 
33
- if @splitted_path.size != splitted_request_path.size
34
- return false
35
- end
32
+ return false if @splitted_path.size != splitted_request_path.size
36
33
 
37
34
  matched_path_pieces =
38
35
  @splitted_path
39
- .map
40
- .with_index do |segment, i|
41
- if segment.start_with?(':')
42
- true
43
- else
44
- splitted_request_path[i] == segment
45
- end
36
+ .map
37
+ .with_index do |segment, i|
38
+ if segment.start_with?(':')
39
+ true
40
+ else
41
+ splitted_request_path[i] == segment
46
42
  end
43
+ end
47
44
 
48
45
  !matched_path_pieces.include?(false)
49
46
  end
@@ -1,50 +1,61 @@
1
- require_relative 'router/route.rb'
2
- require_relative 'router/build_request.rb'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'router/route'
4
+ require_relative 'router/build_request'
3
5
 
4
6
  module Rack
5
7
  class Way
6
8
  class Router
9
+ class UndefinedNamedRoute < StandardError; end
10
+
7
11
  attr_writer :not_found
12
+ attr_reader :route
8
13
 
9
14
  def initialize
10
15
  @routes = {}
11
16
  %w[GET POST DELETE PUT TRACE OPTIONS PATCH].each do |method|
12
- @routes[method] = { _instances: [] }
17
+ @routes[method] = { __instances: [] }
18
+ end
19
+ @route = Hash.new do |_hash, key|
20
+ raise(UndefinedNamedRoute, "Undefined named route: '#{key}'")
13
21
  end
14
22
  @scopes = []
15
- @error = proc { |req, e| raise e }
23
+ @error = proc { |_req, e| raise e }
16
24
  @not_found = proc { [404, {}, ['Not found']] }
17
25
  end
18
26
 
19
27
  def call(env)
20
28
  request_builder = BuildRequest.new(env)
21
- route = match_route(env)
29
+ env['REQUEST_METHOD'] = 'GET' if env['REQUEST_METHOD'] == 'HEAD'
22
30
 
23
- return render_not_found(request_builder.call) if route.nil?
31
+ route_instance = match_route(env)
32
+
33
+ return render_not_found(request_builder.call) if route_instance.nil?
34
+
35
+ if route_instance.endpoint.respond_to?(:call)
36
+ return route_instance.endpoint.call(request_builder.call(route_instance))
37
+ end
24
38
 
25
- if route.endpoint.respond_to?(:call)
26
- return route.endpoint.call(request_builder.call(route))
39
+ if route_instance.endpoint.include?(Rack::Way::Action)
40
+ return route_instance.endpoint.new(@route).call(request_builder.call(route_instance))
27
41
  end
28
42
 
29
- route.endpoint.new.call(request_builder.call(route))
43
+ route_instance.endpoint.new.call(request_builder.call(route_instance))
30
44
  rescue Exception => e
31
45
  @error.call(request_builder.call, e)
32
46
  end
33
47
 
34
- def add(method, path, endpoint)
35
- joined_scopes = '/' << @scopes.join('/')
48
+ def add(method, path, endpoint, as = nil)
49
+ method = :get if method == :head
36
50
 
37
- route = Route.new("#{joined_scopes}#{put_path_slash(path)}", endpoint)
51
+ path_with_scopes = "/#{@scopes.join('/')}#{put_path_slash(path)}"
52
+ @route[as] = path_with_scopes if as
38
53
 
39
- if @scopes.size >= 1
40
- first_level_scope = '/' << @scopes.first
41
- if @routes[method.to_s.upcase][first_level_scope] == nil
42
- @routes[method.to_s.upcase][first_level_scope] = { _instances: [] }
43
- end
44
- @routes[method.to_s.upcase][first_level_scope][:_instances].push(route)
45
- else
46
- @routes[method.to_s.upcase][:_instances].push(route)
47
- end
54
+ route_instance = Route.new(path_with_scopes, endpoint)
55
+
56
+ return push_to_scope(method.to_s.upcase, route_instance) if @scopes.size >= 1
57
+
58
+ @routes[method.to_s.upcase][:__instances].push(route_instance)
48
59
  end
49
60
 
50
61
  def add_not_found(endpoint)
@@ -65,9 +76,23 @@ module Rack
65
76
 
66
77
  private
67
78
 
79
+ def push_to_scope(method, route_instance)
80
+ scopes_with_slash = @scopes + [:__instances]
81
+ push_it(@routes[method], *scopes_with_slash, route_instance)
82
+ end
83
+
84
+ def push_it(h, first_key, *rest_keys, val)
85
+ if rest_keys.empty?
86
+ (h[first_key] ||= []) << val
87
+ else
88
+ h[first_key] = push_it(h[first_key] ||= {}, *rest_keys, val)
89
+ end
90
+ h
91
+ end
92
+
68
93
  def put_path_slash(path)
69
- return '' if (path == '/' || path == '') && @scopes != []
70
- return '/' << path if @scopes != []
94
+ return '' if ['/', ''].include?(path) && @scopes != []
95
+ return "/#{path}" if @scopes != []
71
96
 
72
97
  path
73
98
  end
@@ -78,23 +103,34 @@ module Rack
78
103
  @not_found.new.call(env)
79
104
  end
80
105
 
81
- def match_route(env)
82
- matched_first_level_scope = nil
106
+ def match_route(env, last_tail = nil, found_scopes = [])
107
+ routes =
108
+ if last_tail.nil?
109
+ last_tail = env['REQUEST_PATH'].split('/').drop(1)
110
+
111
+ @routes[env['REQUEST_METHOD']]
112
+ else
113
+ @routes[env['REQUEST_METHOD']].dig(*found_scopes)
114
+ end
83
115
 
84
- @routes[env['REQUEST_METHOD']].each do |first_level_scope, _v|
85
- next if first_level_scope == :_instances
116
+ segment, *tail = last_tail
86
117
 
87
- if env['REQUEST_PATH'].start_with?(first_level_scope) || first_level_scope.start_with?('/:')
88
- matched_first_level_scope = first_level_scope
118
+ routes.each do |scope, _v|
119
+ next if scope == :__instances
120
+
121
+ if segment == scope || scope.start_with?(':')
122
+ found_scopes.push(scope)
89
123
  break
90
124
  end
91
125
  end
92
126
 
93
- if matched_first_level_scope
94
- return @routes[env['REQUEST_METHOD']][matched_first_level_scope][:_instances].detect { |route| route.match?(env) }
127
+ if tail.empty? || found_scopes == []
128
+ return @routes[env['REQUEST_METHOD']].dig(*(found_scopes << :__instances)).detect do |route_instance|
129
+ route_instance.match?(env)
130
+ end
95
131
  end
96
132
 
97
- @routes[env['REQUEST_METHOD']][:_instances].detect { |route| route.match?(env) }
133
+ match_route(env, tail, found_scopes)
98
134
  end
99
135
  end
100
136
  end
data/lib/rack-way.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'rack-way/router'
2
4
  require_relative 'rack-way/action'
3
5
 
@@ -9,12 +11,16 @@ module Rack
9
11
  @router = router
10
12
  end
11
13
 
12
- def app(&block)
14
+ def http_router(&block)
13
15
  instance_eval(&block)
14
16
 
15
17
  @router
16
18
  end
17
19
 
20
+ def route
21
+ @router.route
22
+ end
23
+
18
24
  def scope(name, &block)
19
25
  @router.append_scope(name)
20
26
  instance_eval(&block)
@@ -22,15 +28,7 @@ module Rack
22
28
  @router.clear_last_scope
23
29
  end
24
30
 
25
- def root(endpoint = -> { }, &block)
26
- if block_given?
27
- @router.add('GET', '', block)
28
- else
29
- @router.add('GET', '', endpoint)
30
- end
31
- end
32
-
33
- def not_found(endpoint = -> { }, &block)
31
+ def not_found(endpoint = -> {}, &block)
34
32
  if block_given?
35
33
  @router.add_not_found(block)
36
34
  else
@@ -38,7 +36,7 @@ module Rack
38
36
  end
39
37
  end
40
38
 
41
- def error(endpoint = -> { }, &block)
39
+ def error(endpoint = -> {}, &block)
42
40
  if block_given?
43
41
  @router.add_error(block)
44
42
  else
@@ -47,11 +45,11 @@ module Rack
47
45
  end
48
46
 
49
47
  %w[GET POST DELETE PUT TRACE OPTIONS PATCH].each do |http_method|
50
- define_method(http_method.downcase.to_sym) do |path, endpoint = -> { }, &block|
48
+ define_method(http_method.downcase.to_sym) do |path = '', endpoint = -> {}, as: nil, &block|
51
49
  if block.respond_to?(:call)
52
- @router.add(http_method, path, block)
50
+ @router.add(http_method, path, block, as)
53
51
  else
54
- @router.add(http_method, path, endpoint)
52
+ @router.add(http_method, path, endpoint, as)
55
53
  end
56
54
  end
57
55
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-way
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
  - Henrique F. Teixeira
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-04-21 00:00:00.000000000 Z
11
+ date: 2023-07-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: erubi
@@ -38,7 +38,7 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '3.0'
41
- description: A little web framework that composes well with Rack gems ecossystem
41
+ description: A router and helper functions to build pure Rack projects.
42
42
  email: hriqueft@gmail.com
43
43
  executables: []
44
44
  extensions: []