views:

214

answers:

3

I've created a small application to learn RoR. (Book database) It consists of a read-only area and a read-write admin area.

After I've got the admin functionality working first, I've moved the controller into a subdirectory and created the read-only controller.

Now when I'm updating a book in the admin area, the redirect_to function redirects to the read-only area.

What am I missing?

Here's the code I'm using:

class Admin::BooksController < ApplicationController
  <snip>
  def update
    @book = Book.find params[:id]
    respond_to do |format|
      if @book.update_attributes params[:book]
        flash[:notice] = "Book updated"
        format.html { redirect_to @book }
        format.xml { head :ok }
      else
        <snip>
      end
    end
  end
  <snip>
end

This update itself works but it redirects me to /books/1, but I'd want it to redirect to /admin/books/1. I could just hardcode the correct path, but I guess that's not very good style.

What would be the proper way?

PS: Please comment if you need further information.

+2  A: 

You are telling it to redirect to book because you are using rails' built in magical recognition of what it should do with the @book object (which is build a url to show the book using the book controller.

format.html { redirect_to @book }

If you want it to go elsewhere you need to be explicit about where you want it to go using a hash for url_for

format.html { redirect_to :controller => 'admin/book', :action => 'show', :id => @book   }

or use the paths like klew points out.

so for more detail -

redirect_to (@book) or

redirect_to  book_path(@book)

are both shortcuts for this:

redirect_to :controller => book, :action => 'show', :id => @book.id

srboisvert
You are saying "using the book controller". But why is the 'other' book controller chosen? Can I control somehow which controller is preferred?
DR
Probably redirect_to @book looks on object @book (not on the controller you are in) and try to find default controller - that's why you are redirected outside the admin namespace.
klew
When you say redirect to @book rails' internal code converts that to the book controller and the default action for a single book object (show). It's a nice syntactic sugar shortcut but it unfortunately also hides what is going on from newbies.
srboisvert
+2  A: 

Rails creates for you url helpers based on your routes.rb. If you have namespace then you can use this:

admin_book_path(@book)        # admin/books/2
admin_books_path              # admin/books
edit_admin_book_path(@book)   # admin/books/2/edit

and so on.

The other way is to use resource_controller it creates for you controller automaticaly and provides some ways to modify it if it's needed. It also gives you some useful url helpers

collection_path               # admin/books
object_path                   # admin/books/2

When you use above helpers in views, than it generates url with namespace if you are in one, or without namespace otherwise.

resource_controller isn't perfect, but in most cases it works good and saves a lot of work.

klew
+1  A: 

You can also pass an array to redirect where the first element is a symbol representing the namespace, and the second the element the object.

redirect_to [:admin_book, @book]

You can also use this for form_for, link_to and any other helpers that require a path.

I tested it and I changed the code, so that it actually works and removed "I think".
DR