craig
craig

Reputation: 26262

Rails 3 add GET action to RESTful controller

I have a controller with the 7 RESTful actions plus an additional 'current' action, which returns the first active foo record:

class FooController < ApplicationController

  def current

    @user = User.find(params[:user_id])
    @foo = @user.foos.where(:active => true).first

    #use the Show View
    respond_to do |format|
      format.html { render :template => '/foos/show' }
    end

  end

  #RESTful actions
  ...

end

The Foo Model :belongs_to the User Model and the User Model :has_many Foos.

If I structure the routes as such:

resources :users do
  resources :foos do
    member do
      get :current
    end
  end
end

The resulting route is '/users/:user_id/foos/:id'. I don't want to specify the foo :id, obviously.

I've also tried:

map.current_user_foo '/users/:user_id/current_foo', :controller => 'foos', :action => 'current'
resources :users do
  resources :foos
end

The resulting route is more like I would expect: '/users/:user_id/current_foo'.

When I try to use this route, I get an error that reads:

ActiveRecord::RecordNotFound in FoosController#current
Couldn't find Foo without an ID

edit

When I move the current action to the application controller, everything works as expected. The named route must be conflicting with the resource routing.

/edit

What am I missing? Is there a better approach for the routing?

Upvotes: 1

Views: 1326

Answers (1)

Doon
Doon

Reputation: 20232

I think you want to define current on the collection, not the member (the member is what is adding the :id).

try this.

resources :users do
  resources :foos do
    collection do 
      get :current
    end
  end
 end

Which should give you a route like this:

 current_user_foos GET    /users/:user_id/foos/current(.:format)         {:controller=>"foos", :action=>"current"}

Also map isn't used anymore in the RC, it will give you a deprecation warning.

Upvotes: 3

Related Questions