Search code examples
ruby-on-railsroutescustom-actioncustom-routes

Ruby on Rails - Setting a Custom Route with Custom Action


i'm a RoR beginner using rails 3.2.3.

I have a products resource and a nested Availability resource under it.

My routes are:

/products/:product_id/availabilities

which is working great.

However, my availability model allows to set the price of the product on an exact date, for e.g.: today the product 'x' will have 'y' availability (it is an integer) and 'z' price (price is also an attribute of the Availability Model).

My question is, I now want to add a page that allows the modification of prices (without creating a new Price Model), similar to the one I have for availability. I'm only using the index action, as it will show all the availabilities for that only selected product.

How can I create a route like:

/products/:product_id/availabilities/prices

I tried adding this to my routes rb:

 match '/products/:id/availabilities/prices', :action => 'indexP', :via => [:get], :controller => 'prices'
 match '/products/:id/availabilities/prices', :action => 'createP', :via => [:post], :controller => 'prices'

It is worth noting that I am using a prices controller to interact with the same availability model, but that shouldn't be a problem.

I also created in that prices controller the indexP and createP actions. In my Availabilities View I created an indexP.html.erb to differentiate from the regular index.html.erb which contains the availabilities.

And when I run rake routes I get:

$ rake routes | grep prices
                            GET    /products/:id/availabilities/prices(.:format)
                            POST   /products/:id/availabilities/prices(.:format)

Which is great. However, when I access that URL, I get:

NoMethodError in Availabilities#show
{"product_id"=>"46",
 "id"=>"prices"}

Why is it doing the show action instead of my custom match?

Note: I am not after something like: /products/:id/availabilities/:id/prices

just :/products/:id/availabilities/prices

I know this is probably a dumb question but I would appreciate any tips to help me understand what is going on.

Thanks in advance, regards


Solution

  • How is your product model setup?

    If it something like:

    resources :products do
      resources :availabilities
    end
    

    the first match the route does goes to the show action of the availabilities controller.

    You have two options here. Limit the availabilities controller scope, with:

    resources :products do
      resources :availabilities, :only => [:index]
    end
    

    or to place your custom match before this block

    match '/products/:id/availabilities/prices', :action => 'indexP', :via => [:get], :controller => 'prices'
    match '/products/:id/availabilities/prices', :action => 'createP', :via => [:post], :controller => 'prices'
    

    Note that this routes are not restfull. This may get you in trouble later :)

    Hope this helps.