rack-way 0.0.2 → 0.0.3

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.
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: []