Ruby on Rails/Routing

From Wikibooks, open books for an open world
< Ruby on Rails
Jump to: navigation, search

Because Routing is such an important part of Rails we dedicated a whole chapter to Routing (even though they are part of ActionView).

For example, if you want to display the product with the id 4, you will use a link similar to products/4. So Rails will figure out, that you want to show the information that belongs to the product with the id 4.

Routing also works when you want to link somewhere from one point of your application to another point. If you want to go back from the products view to the index overview that displays all products, you may place something like this in your view:

 <%= link_to 'Back', products_path %>

When writing your own routes inside routes.rb, keep in mind, the lower the route is inside your file, the less priority it has.

Understanding Routes and Routing[edit]

RESTful routes[edit]

RESTful routes are the default routes in Rails. To get a more detailed technical view on REST, check out the Wikipedia article.

Basically REST provides a way of communication inside your application and all requests that exist from external sources (just as a browser request). To understand these principles better, take a look the following table:

HTTP Verb URL Controller Action used for
GET /products Product index display all products in an overview
GET /products/new Product new return an HTML form for creating a new product
POST /products Product create create a new product
GET /products/1 Product show display a specific product
GET /products/1/edit Product edit return an HTML form for editing a product
PUT /products/1 Product update update a specific product
DELETE /products/1/ Product destroy delete a specific product


As you can see, all the actions of REST are already in our scaffolded controller. Keep in mind that RESTful routes reference a single object (products in this case). These 7 actions would result in a single route inside routes.rb:

map.resources :products

With a RESTful resource, it's easy to link the different views together or link to a specific view. With REST, Rails provides us some helpers to get to our desired location:

  • products_url & products_path => redirects us to the index overview and edit view for our products (note the plural)
  • new_product_url & new_product_path => will lead as to the form that creates a new product
  • edit_product_url & edit_photo_path => provides us with an edit-form for a specific product
  • product_url & product_path => is responsible for showing, deleting and updating a product


While *_path will create a relative path to, *_url provides the whole URL


You will very likely need more than one REST route. You can easily write multiple REST routes into a single:

map.resources :products, :categories, :customers


You will come across many similar constructs like our products-category relation:

class Category < ActiveRecord::Base
  has_many :products
end
 
class Product < ActiveRecord::Base
  belongs_to :categories
end
HTTP Verb URL Controller Action used for
GET /products/1/categories Category index will show you an overview of the categories for product with the id 1
GET /products/1/categories/new Category new will give you an HTML form to create a new category for product with id 1
POST /products/1/categories Category create will create a new category for product with id 1
GET /products/1/categories/1 Category show shows you the categories with id 1 that belongs to your product with id 1
GET /products/1/categories/1/edit Category edit gives you an HTML form to edit your category with id 1 that belongs to product with id 1
PUT /products/1/categories/1 Category update updates category with id 1 that belongs to product with id 1
DELETE /products/1/categories/1 Category destroy deletes category with id 1 that belongs to product with id 1


As with resources that are not nested, you will be able to access all *_url and *_path helpers e.g. products_categories_path or new_product_category_url

These path need to be present in your routes.rb in an similar maner to your model:

map.resources :products, :has_many => :categories

if you need to add more than one association, put these in []

which is the same as the following route, only shorter

map.resources :magazines do |magazine|
  magazine.resources :ads
end

With this way, you can nest as many resources as you want, but you should try to keep the level of nesting as low as possible. So one nested resource is ok, but try to avoid 2 or more. To avoid these problems, we can use "shallow nesting"

If we want to add supplier for specific categories, we may end up with something like

map.resources :publishers, :shallow => true do |publisher|
  publisher.resources :magazines do |magazine|
    magazine.resources :photos
  end
end

or in short:

map.resources :products, :has_many => { :categories=> :suppliers }, :shallow => true

There are many more advanced features for routing. More infos and instructions can be found in the official Rails guides.

Regular Routes[edit]

Even though RESTful routes are the encouraged way to go, you can also use regular routes inside your application. When working with regular routes, you give Rails some keywords and it will map the proper path for you. One of these default routes is already inside your routes.rb (this time we don't use .resources but .connect)

map.connect ':controller/:action/:id'

will for example be a browser request similar to products/show/2

If you are familiar with other languages that focus an the web, you may wonder how query strings inside the URL are handles: Rails automatically provides these parameters inside the params hash

So if you take the example above and add products/show/2?category=3, we would be able to access the category id with params[:category_id].

See also[edit]

The API with lots of examples