Skip to content

Rails: Following the program flow

Sean Lerner edited this page Apr 12, 2017 · 1 revision

When following the flow of a Rails program, think about the HTTP Request Response Cycle and how Rails processes each request.

Most http requests follow this flow:

  1. The browser sends the request to the server (if you're issue is happening while developing, then the browser is likely sending the request to IP Address 127.0.0.1 (localhost), TCP Port 3000.

  2. Rails looks up the request in its Routing table

  3. Rails sends the request on to the appropriate Controller

  4. Rails invokes the appropriate Action (aka method) in the Controller

  5. Your Controller Method uses Model(s)

  6. Your Models communicate with the Database

  7. Your Controller Method renders a View and Layout

  8. The response is send back to the browser

How To Fix

Step 1. Identify the HTTP request method being sent:

GET - if the URL was entered into a browser's location bar and enter was pressed, or if a regular link was clicked

POST - if a form submit button was clicked to create a new record

PUT & PATCH - if a form submit button was clicked to update an existing record

DELETE - if a link with the method set to delete was clicked

Step 2. Identify the path of the HTTP request:

Take a look at the URL being sent:

For GET requests: the URL will be in the browser's location bar.

For POST, PUT and PATCH requests: you can see the URL by using debugging tools to inspect the <form> tag. Within the <form> form tag is an action attribute. This will be set to the URL or PATH.

For DELETE requests, inspect the delete link using debugging tools and look at the href attribute.

A URL is made up of several parts:

  • Protocol: http or https
  • Hostname: localhost
  • Port number: 80 or 3000 (sometimes this isn't visible)
  • Path: the segment between the Hostname/Post Number up until either the end of the URL, or until the first ?, whichever comes first. Note the the path can also be empty if nothing follows the Hostname/Post Number
  • Parameters: everything that follows the ? (not necessarily present)

e.g.

  • http://localhost:3000/products/new - the path is products/new
  • http://localhost:3000/ - the path is empty
  • http://localhost:3000/search?q=my+search+terms - the path is search

Step 3. Match the http request method and path with the route

Take a look at your routes using:

rails routes

on the command line.

You should see something like this:

      Prefix Verb   URI Pattern                  Controller#Action
    products GET    /products(.:format)          products#index
             POST   /products(.:format)          products#create
 new_product GET    /products/new(.:format)      products#new
edit_product GET    /products/:id/edit(.:format) products#edit
     product GET    /products/:id(.:format)      products#show
             PATCH  /products/:id(.:format)      products#update
             PUT    /products/:id(.:format)      products#update
             DELETE /products/:id(.:format)      products#destroy

Match the HTTP Request Method you obtained in the previous step with the VERB column.

Match the PATH you obtained in the previous step with the URI Pattern column:

When matching against a URI Pattern, break the Pattern into segments, with each segment being in between two slashes. For example:

/products/new - products is one segment, new is another segment.

Figure out if each segment is a static or dynamic segment:

  • static segments do not begin with a : (colon)
  • dynamic segments begin with a : (colon)

Match each segment with the PATH:

  • static segments need to match exactly
  • dynamic segments are wildcards, and can match against anything

note: you can ignore the (.:format) portion of the URI Pattern for regular web page requests.

Example 1

http://localhost:3000/products matches:

  Prefix Verb   URI Pattern                  Controller#Action
products GET    /products(.:format)          products#index
Example 2

http://localhost:3000/products/99 matches:

  Prefix Verb   URI Pattern                  Controller#Action
 product GET    /products/:id(.:format)      products#show

Step 4. Match the route with the appropriate controller and action

Now that you know the route, look at the Controller#Action column to see what controller and what method is being invoked.

For example, if you identified the following route as matching:

  Prefix Verb   URI Pattern                  Controller#Action
products GET    /products(.:format)          products#index

Then you would open the ProductsController and go to def index.

Step 5. Follow the flow of the method

Starting the top of your method, try to understand each line of code. If another method is called, follow the flow to that method and then back to the next line of this method.

Unless a render or redirect is explicitly called, the controller will attempt to render a template based on the Controller and Method name.

Example

A typical method for deleting a record:

def destroy
  @product = Product.find(params[:id])
  @product.destroy!
  flash[:notice] = 'Product successfully deleted.'
  redirect_to products_url
end

Let's break this down. First:

  @product = Product.find(params[:id])
  • an instance variable @product is created
  • the method find is called on the Product class
  • the params hash is accessed with :id as the key
  • the params[:id] returns a value (whatever :id was set to in the path)
  • the value returned from params[:id] is passed as an argument to the find method
  • the find methods executes SQL to find a record
  • the find method creates an instance of Product, and populates it with the data retrieved from the SQL statement
  • the instance of Product is assigned to be the value of @product

... then:

  @product.destroy!
  • the destroy! method is called on @product, which is an instance of Product
  • an SQL statement to delete the record is sent to the database

... then:

  flash[:notice] = 'Product successfully deleted.'
  • the flash hash key :notice is set to the value 'Product successfully deleted.'
  redirect_to products_url

... then:

  • the redirect_to method is called
  • the products_url method is called
  • the products_url method returns the value http://localhost:3000/products
  • the value http://localhost:3000/products is passed as an argument to the method redirect_to
  • the redirect_to method redirects the browser to the page http://localhost:3000/products

... and then you need to follow the flow of the new request to http://localhost:3000/products.

Step 6

If you still haven't found the solution to your issue, try the other techniques listed on Rails program runs with unexpected results page

Clone this wiki locally