1 Request life cycle in Ruby on Rails application (part 2)

Tram Ho

Following the previous section, we will together find a solution for the relationship between App Server, Web Server and Rails ^^

What is a rack?

Rack is the answer to the previous question. Rack can be understood as a common convention (a protocol) for App Server to communicate with Ruby Web Framework (such as Rails, Sinatra or Padrino) and vice versa.

For example, the App server (Puma) receives a request from the Web Server (Nginx) – the above Blog problem, for example. Puma will pass that request to Rack and Rack will communicate with Web Framework (Rails). Rails will handle the problem in Ruby and respond (in a different way).

Basically a life cycle then looks like this

Request HTTP -> Web Server (Nginx) -> App Server (Puma) -> Rack -> Ruby Web Framework (Rails)

The end result will look like this:

Before diving into Rails, let’s try to build a simple Rack application

This can be understood as one of the simplest Rack applications we can build. It doesn’t have a class or anything else involved, it’s simply a class that declares the call method. It will check the request env from env , if it matches the path /blog , it will respond to the simple text Blog , otherwise it will have to return 404 and Not Found text

Okay, now that we have written our application, how do we use it? How do we connect everything? Recall that Rack is just a protocol that web servers can implement, so we’ll need to connect our application to a Rack-aware web server.

Luckily, in Ruby we have a library called Gem . It’s Rack gem – a library of all utilities to make and use Rack. Configuration call to the class above will be as follows

This is basically a Ruby file with some additional DSL configuration. Here, we require building and using a version of the Blog application and passing it to the rackup server using DSL run

With that, we can run the rackup command from the directory of the config.ru file and it will attach the server to port 9292 by default. If we visit http://localhost:9292/blog , we will see “Blog” and if we navigate to http://localhost:9292/xxx , we will see the “Not Found” error.

Now we modify a bit to specify the path to root / to /blog as follows:

Try it again … of course it works fine, but not good. If we add a lot of paths here, then if . elsif . else forever and ever ???

Redirect is a basic task so we need to rewrite it better to use it for multiple places in our application. So we’ll find ways to rewrite it in a module and reuse it everywhere.

In the above writing, we basically keep the same logic as the Blog class . However, we will add a Redirect class to handle general requests. If the request matches the path it will give the redirect response and finish. If not, it will authorize the next application we have written.

Next we change config.ru as follows

We build an instance of the Blog application and pass it to the Redirect application. In this way, we have deployed an intermediary called the Rack middleware . However, the middleware is not part of Rack’s technique – it is only part of the app we wrote above (Redirect). It just “happens to” call another Rack application as part of the #call method, and the web server doesn’t need to know this.

The pattern middleware is so popular that config.ru has a dedicated DSL keyword for it

middleware pattern really “strong”. We don’t need to write any more code here, simply add some config middleware from the rack gem:

This is how we build a Redirect application

Rails ❤️ Rack

We are finally ready with Rails.

Of course, Rails will deploy Rack already. If you look at your Rails application, it will come with a config.ru file that looks like this:

Although config.ru is derived from rackup , it is also understood by some other servers and web services such as Heroku, so Rails may include it by default.

As we learned at the beginning of the article, we have to transfer a Rack application for the run keyword, so Rails.application must be a Rack application that responds to #call . We will try a bit with the rails console

Instead of rewriting an env hash manually, we can use Rack::MockRequest.env_for – a method from rack gem.

One thing that stands out from the config.ru file in our Rails application is that it doesn’t have any user statements. Does Rails use any middleware? Is not! In fact, there is a handy command that you can run to see all the middleware in your application using the familiar config.ru syntax:

We can see that Rails has implemented many of its functions in intermediary software, such as cookie handling. This is great, because if we are deploying an API server, we can remove these unnecessary middleware. But how?

Recall that using statement is only a convenience in building your application in config.ru , the web server only “sees” the most external application. Rails has a different convenience for managing middleware in config/application.rb :

Final …

So we looked at middleware, but where are our “apps”? The answer is from the output of the bin/rails middleware , and we need to know how to use and run this middleware for our application. And Blorgh:Application.routes was born.

The Rack application looks at the URL requets, matches a series of routing rules required to find the appropriate controller or action called. Rails gives you a place to declare these things, it’s written in config.routes.rb .

DSL resources look familiar to Rails application developers. It is a concise syntax to define a series of routes at once. Fully written, it will include the following 7 routes

For example, when you make a GET request to /blogs , it will call the BlogsController#index , if you make a PUT request to /blogs/:id , it will go to BlogsController#update .

So … what are the blogs#index series? It is simply an abbreviation for the action index in BlogsController . If you learn the code of Rails, you will find that it will eventually expand to BlogsController.action(:index) .

Finally, putting everything together, you can imagine the routing application is a rack application that looks like this:

It matches the given request path and http verbs against the rules defined in your config routes and authorizes the appropriate Rack application on the controller . The good thing is you don’t have to write everything on by hand. Thanks Rails!

summary

In this article, I have basically introduced the life cycle of a request in the Rails application, from the receipt of the end-user request in the browser, to the way that the request is sent to handle in the Rails controller .

thank you for watching

The article was translated and referenced from:

https://blog.skylight.io/the-lifecycle-of-a-request/

Share the news now

Source : Viblo