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.