We're almost done. The reason we added the render method to the controller class is to call it from the router, once the instance variables are set.

Modify the router's get method so it looks like this.

def get(path, &blk)
  if blk
    @routes[path] = blk
  else
    @routes[path] = ->(env) {
      controller_name, action_name = find_controller_action(path)   # 'articles', 'index'
      controller_klass = constantize(controller_name)               # ArticlesController
      controller = controller_klass.new(env)                        # controller = ArticlesController.new(env)
      controller.send(action_name.to_sym)                           # controller.index

      controller.render("views/#{controller_name}/#{action_name}.html.erb")
    }
  end
end

The most important point is that we've separated the action-calling and response-rendering mechanisms.

Before, we were simply calling the action method on the controller and returning whatever response the action method returned.

Now, we first call the action method so that it gets a chance to set the instance variables. Then, we call the render method we just created, and pass it the name of the dynamically generated view template views/articles/index.html.erb following Rails conventions.

Inside the render method, the instance variables are already set, since it's the same controller instance. Hence it can render the view template without any problem.

We now have all the pieces in place. The only thing remaining is to use them. Let's update the controller so it sets the instance variables and add a view template that uses the instance variables.