Thanks to visit codestin.com
Credit goes to github.com

Skip to content
ngollan edited this page Jul 20, 2011 · 4 revisions

The merb router is found in $MERB_ROOT/config/router.rb. It will by default contain a block that looks like:

Merb::Router.prepare do
  # RESTful routes
  # resources :posts

  # This is the default route for /:controller/:action/:id
  # This is fine for most cases.  If you're heavily using resource-based
  # routes, you may want to comment/remove this line to prevent
  # clients from calling your create or destroy actions with a GET
  default_routes

  # Change this for your home page to be available at /
  match('/').to(:controller => 'reports', :action =>'index')
end

Resources

As the comments mention, you can add a resource to the router by adding the following code within the Merb::Router.prepare block

resources :cars

Friendly URLs

Resources use the model's id in the URL by default, but this can be overridden using the identify block or a parameter to the resource definition to make a URL more readable. For instance, the following code uses the model's slug.

  identify Car => :slug do
    resources :cars
  end

  # or alternatively:
  resources :cars, :identify => :slug

Your controller must be changed to find the Car by slug. The show action would look something like that:

  def show
    @car = Car.first(:slug => params[:slug])
    raise NotFound unless @car
    display @car
  end

Nested Resources

The router allows you to nest models. The following code, nests Cars within CarModels, which are in turn nested within Makes.

  resources :makes do
    resources :car_models do
      resources :cars
    end
  end

With the above code you would then access cars with the URL http://localhost:4000/makes/5/car_models/10/cars/15.

You can now generate URLs for your nested resources using the following format:

   url(:make_car_model_cars, @car.car_model.make, @car.car_model)
   url(:make_car_model_car, @car.car_model.make, @car.car_model, @car)
   url(:edit_make_car_model_car, @car.car_model.make, @car.car_model, @car)

Bringing It All Together

Finally, you can combine the identify block for friendly URLs with nest resources. The following code nests Cars within CarModels within Makes, and uses their slugs instead of their ids for access.

  identify Make => :make_slug do
    resources :makes do
      identify CarModel => :model_slug do
        resources :car_models do
          identify Car => :car_slug do
            resources :cars
          end
        end
      end
    end
  end

NOTE: currently the identify attributes are passed in with the name you give them here, so when nesting resources, they must have different identifiers. If you named them all "slug", then you will only get one of them passed into your controller.

Unless your slugs are all globally unique, your controller's show action would look something like:

  def show
    @car = Make.first(
             :make_slug => params[:make_slug]
           ).car_models.first(
             :model_slug => params[:model_slug]
           ).cars.first(
             :car_slug => params[:car_slug]
           )
    raise NotFound unless @car
    display @car
  end

If you use action-args to make your controllers more readable, your show action might look more like the following:

  def show(make_slug, model_slug, car_slug)
    @car = Make.first(
             :make_slug => make_slug
           ).car_models.first(
             :model_slug => model_slug
           ).cars.first(
             :car_slug => car_slug
           )
    raise NotFound unless @car
    display @car
  end
Clone this wiki locally