Let's create a new Router class in the current directory as follows. It maintains a @routes Hash as the internal data structure to store the URL patterns along with their corresponding handlers.

A handler is simply a Ruby block that will be called when our app receives a request to the corresponding path.

# weby/router.rb

class Router
  def initialize
    @routes = {}
  end

  def get(path, &blk)
    @routes[path] = blk
  end

  def build_response(path)
    handler = @routes[path] || -> { "no route found for #{path}" } 
    handler.call 
  end
end

For a deeper understanding of blocks, procs, and lambdas, check out the following post: Blocks, Procs, and Lambdas: A Beginner's Guide to Closures and Anonymous Functions in Ruby

The get method takes a URL path and a block as arguments. The block represents the handler code that should be executed when a request matching that path arrives. It then stores the path along with the handler in the @routes hash.

def get(path, &blk)
  @routes[path] = blk
end

Finally, the build_response method takes the path of the current request. It finds the corresponding handler from the @routes mapping. If the path is not stored in the mapping, we set the handler to a default lambda that returns the message no route found.

After we find the handler block for the current path, we call it and return the generated output back to the application.

def build_response(path)
  handler = @routes[path] || -> { "no route found for #{path}" } 
  handler.call 
end