RESTful admin namespaced controller using scaffolding 24

Posted by Slobodan Kovačević on September 17, 2008

Most of my clients prefer to have a separate admin section. In turn, I like to have separate controllers for admin section and front-end in my Rails app. This is not as straightforward as it might seem, especially if you like to use scaffolding for admin controller.

The goal is to get 2 separate RESTful controllers, admin & front-end controller, one model and for admin pages to have scaffolding.

Here is the easiest way I found so far to accomplish this. This example generates categories model and controllers for it.

./script/generate controller admin/categories
./script/generate scaffold category name:string

This will generate an empty controller in admin namespace and a scaffolded resource for front-end controller.

Now we have everything generated we just need to make it work with admin controller and not with front-end.

  • move all templates from app/views/categories to app/views/admin/categories
  • copy all functions from categories_controller.rb to admin/categories_controller.rb
  • add namespace for admin controller in routes.rb:map.namespace :admin do |admin|
    admin.resources :categories
    end
  • in admin/categories_controller.rb replace in 3 places redirect_to calls to work with admin namespace. It will have something like redirect_to(@category), but to work with namespace it needs to have redirect_to([:admin, @category])
  • make similar changes in all templates, i.e. make it work within an admin namespace. You need to make following changes:
    • form_for(@category) => form_for([:admin, @category])
    • <%= link_to ‘Show’, @category %> => <%= link_to ‘Show’, [:admin, @category] %>
    • categories_path => admin_categories_path
    • edit_category_path(@category) => edit_admin_category_path(@category)
    • new_category_path => new_admin_category_path

That’s it. Now you’ll have /admin/categories for all administrative tasks and you have a free controller for front-end actions.

You might wonder why not just generate scaffold for admin/categories… The reason is that you’ll also get a model that is namespaced in admin (i.e. model would be Admin::Category). Scaffolded views also wouldn’t work as it seems that generator doesn’t take into account the fact that you are using a namespace.

Share/Save/Bookmark

Trackbacks

Use this link to trackback from your own site.

Comments

Leave a response

  1. john Sun, 28 Dec 2008 04:44:12 UTC

    the following doesn’t work for me:

    script/generate controller admin/categories

    I’m doing script/generate controller user/accounts
    and I get the error:
    The name ‘user’ is either already used in your application or reserved by Ruby on Rails.
    Please choose an alternative and run this generator again.

    I would’ve expected this to generate an accounts_controller in the user namespace. I’m toying with the restful authentication framework, where this code has come from..

  2. Glenn Fri, 23 Jan 2009 00:09:22 UTC

    Now what about the functional tests? I was just messing with scaffolding today after being a long-time hand coding guy. It’s unfortunate you cannot just specify the namespace for the controller since this is such a common practice (especially for admin site as you noted).

  3. James Mon, 09 Feb 2009 02:59:51 UTC

    Awesome!

    Thank you

  4. James Thu, 12 Feb 2009 23:28:12 UTC

    I’ve been playing with this for a couple of days now and have found that it works perfectly for the scaffolded and model based routes.
    I am totally hooked on this solution but I am struggling with non model based routes.

    for example a generated admin/home controller on it’s own does not seem to like routes for link_to commands

    If I am trying to render a non model view with a link_to command I would normally use the :controller parameter. As this controller is now in an admin folder I’m faced with calling

    link_to(”Administration”, :controller => ‘admin/home’)
    Whilst this works it doesn’t ‘feel’ very restful and was wondering if you handle this scenario differently?

    Thanks

    James

  5. Slobodan Kovačević Fri, 13 Feb 2009 11:56:41 UTC

    I don’t think that there another way. That’s the only way to reference namespaced controller.

  6. Zoran Sat, 09 May 2009 10:38:37 UTC

    Good trick Slobo! Sadly there’s no other way.

  7. Andre Mon, 18 May 2009 04:29:34 UTC

    Thank you so much. Exactly the information I needed, not that pretty but now I can do what I want to achieve.

  8. Mike Fri, 10 Jul 2009 00:06:22 UTC

    This was exactly what I was looking for. Thank you for making this info available…I’d have never figured out the wonky namespace head-standing/hair-pulling required in the views.

    Thanks!

    ( I await the day I can script/generate scaffold Namespace::Thing, tho and have the models “work” and the resources “work” )

  9. [...] an admin area to do all the backend stuff to manage all your content and users. [icebergist] gives one way of adding an admin area to your web [...]

  10. Marcos Sat, 22 Aug 2009 06:28:38 UTC

    Thank you very much, you saved my life! =D
    I was trying all day to make this work and this post was exactly what I was looking for! I’m new to Ruby on Rails so i’m still getting how it really works… thk u very much!

  11. Daniel Mon, 21 Dec 2009 01:39:32 UTC

    Thanks for the really helpful code. I’m trying to do this operation with admin and users (rather than categories) but getting a path error.

    The links in my admin/users index.html.erb page are causing errors. For example, the first “show” link is causing an “undefined method `admin_path’ for

    Here’s the offending code on my index.html.erb

    ‘Are you sure?’, :method => :delete

    I have the following in my routes….

    map.namespace :admin do |admin|
    admin.resources :users
    end

    Any thoughts on what I’ve done wrong? Thanks in advance for any help or suggestions!

    Daniel

  12. Daniel Mon, 21 Dec 2009 01:41:21 UTC

    …arrrgh, the code got cut out. Here’s the problematic code:

    ‘Are you sure?’, :method => :delete %>

  13. Daniel Mon, 21 Dec 2009 01:42:16 UTC

    …[head thumps against wall]…

    link_to “Show”, [:admin, @user]
    link_to “Edit”, edit_admin_user_path(@user)
    link_to “Destroy”, user, :confirm => ‘Are you sure?’, :method => :delete

  14. Zak Sun, 10 Jan 2010 23:36:45 UTC

    Do you think it’d be possible for you to teach us how to password protect the admin namespace?

  15. Slobodan Kovačević Mon, 11 Jan 2010 11:46:35 UTC

    Zak, to “protect the namespace” you actually need to limit access to each controller (their actions to be precise) within that namespace. Usually you will add some before_filters that will handle authorization. Something like this:

    before_filter :admin_only

    Exact way to do this varies depending on what you use (if any) as an user system. For example, if you use Clearance you can do like this: http://wiki.github.com/thoughtbot/clearance/admin

  16. pawel Tue, 12 Jan 2010 14:37:19 UTC

    Thanks Slobodan, it’s a very useful tutorial. I have a one question: is it exists some newer solution? I ask you because this was posted on September 2008.

    Greetings from Poland

  17. Jamesw Thu, 14 Jan 2010 21:04:23 UTC

    @Daniel the destroy link should use the [:admin, user] notation.
    link_to ‘Destroy’, [:admin, theme], :confirm => ‘Are you sure?’, :method => :delete

  18. Ankit Varshney Tue, 16 Feb 2010 06:21:23 UTC

    Why don’t we move user model in admin folder? Like admin\user.rb and also changing the class name to Admin::User. By doing this there is no need to put :admin in any RESTful path.

  19. Ankit Varshney Tue, 16 Feb 2010 06:27:33 UTC

    And also there is no need to run two separate commands one for controller and one for scaffold. Simply run :

    ./script/generate scaffold admin/user name:string

    This is true for Rails 2.3.5.

  20. Slobodan Kovačević Tue, 16 Feb 2010 12:41:52 UTC

    @Ankit The whole point is to have one model which is used for both frontend and admin controllers.

  21. Reinaldo Thu, 18 Mar 2010 22:32:11 UTC

    Is it possible to create a command like

    ./script/generate scaffold_admin user name:string

    and the structures will be created on the right places?

  22. Slobodan Kovačević Fri, 19 Mar 2010 10:00:40 UTC

    @Reinaldo As far as I know there’s no option to generate scaffold specifically for certain namespace.

  23. Daren Fri, 26 Mar 2010 19:27:18 UTC

    @Jamesw – for me the destroy link actually goes to the Show Action, rather than destroying the record.

    Did anyone else have the same problem? Has anyone got a solution for this?

  24. Daren Fri, 26 Mar 2010 20:04:30 UTC

    Sorry ignore my previous comment, it was simply a Rails 3 Beta issue, I was not including the default javascript files, specifically rails.js and prototype.js…all working fine now!

Comments