Class: FileSystemRouting
- Inherits:
-
Object
- Object
- FileSystemRouting
- Extended by:
- StringUtils
- Defined in:
- lib/routing/file_system.rb
Overview
A file-system based router, like Next.js
Class Method Summary collapse
-
.regexp_of_name(const_name) ⇒ Object
::Hello => ^/hello$ ::Hello::X => ^/hello/(\w+)$.
- .register_route!(cpath, value) ⇒ Object
- .root(dir) ⇒ Object
- .routes ⇒ Object
Instance Method Summary collapse
Methods included from StringUtils
Class Method Details
.regexp_of_name(const_name) ⇒ Object
::Hello => ^/hello$ ::Hello::X => ^/hello/(\w+)$
35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/routing/file_system.rb', line 35 def regexp_of_name(const_name) # namespace inner = const_name.split('::').map do |part| case part when 'Index' then '' when 'X' then '(\w+)' when 'N' then '(\d+)' else snake_of_pascal(part) end end.join('/') Regexp.new("^/#{inner}$") end |
.register_route!(cpath, value) ⇒ Object
48 49 50 51 52 53 54 |
# File 'lib/routing/file_system.rb', line 48 def register_route!(cpath, value) return unless value.method_defined? :call routes << { method: 'GET', pattern: regexp_of_name(cpath), module: value } end |
.root(dir) ⇒ Object
56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/routing/file_system.rb', line 56 def root(dir) from_dir = File.dirname(caller.first.split(':').first) @root = File.join(from_dir, dir) loader = Zeitwerk::Loader.new loader.on_load do |cpath, value, _abspath| register_route! cpath, value end loader.push_dir(@root) loader.setup loader.eager_load end |
.routes ⇒ Object
28 29 30 |
# File 'lib/routing/file_system.rb', line 28 def routes @routes ||= [] end |
Instance Method Details
#call(env) ⇒ Object
10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# File 'lib/routing/file_system.rb', line 10 def call(env) route = self.class.routes.find do |route| route[:method] == env['REQUEST_METHOD'] and route[:pattern] =~ env['PATH_INFO'] end if route # Call the module's `call` method obj = Object.new.extend route[:module] result = obj.call env, *Regexp.last_match.captures [200, { 'content-type' => 'text/html' }, [result]] else [404, { 'content-type' => 'text/html' }, ['404 Not Found']] end end |