RESTful admin namespaced controller using scaffolding 35

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
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!

  25. Jerret Fri, 20 Aug 2010 20:18:45 UTC

    Thanks, the changes to fix the scaffolding were just what I needed.

  26. Rob Hayward Mon, 06 Sep 2010 12:56:53 UTC

    Great article!! Just what I was after, thanks for that.

    What exactly is [:admin, @category] doing? Just prefixing ‘/admin/’ in the path?

    Does this technique have a name or is just modifying routes

    Thanks
    Rob

  27. Jamesw Tue, 28 Sep 2010 21:45:29 UTC

    Slobodan Kovačević,
    Just an addition to the above to make the process complete

    In the admin controller wherever you see a location for the XML response you also need to add the admin name space so if you have something like

    format.xml { render :x ml => @email_notification, :status => :created, :location => @email_notification }

    You should change it to say
    format.xml { render :x ml => @email_notification, :status => :created, :location => [:admin, @email_notification] }

  28. Rails 3練習筆記 | Mr. Big Cat Sat, 29 Jan 2011 20:02:41 UTC

    [...] Admin namespace我是照這篇做的,做了看版管理及文章管理。就一般論壇而言,像「看版管理」這種東西,一般人不會有新增、修改、刪除的權限(版主可能有修改),所以scaffold架出來的東西應該的確比較適合移到admin去,而給使用者的邏輯再手動打造。但我的實作有種不夠DRY的感覺,把view和controller的code複置兩份,感覺不太好。可以想見,其實可以利用繼承、共用函式等方式,將程式碼變的更精簡。這部份有更好的best practice嗎? ( 6)用 Rake 撰寫自動化步驟,生假資料。寫一個 rake 可以達成以下步驟:「砍 db => 建 db => 跑 migration => 生種子資料」,另一個 rake 是生假文章與假論壇。 [...]

  29. Viktor Fri, 01 Apr 2011 21:41:59 UTC

    Thanks!!! That’s what I was looking for :)

  30. M Awais Tue, 03 May 2011 10:54:09 UTC

    I am using rails 3 and I have followed all the steps but I am facing problem i.e.
    Extracted source (around line #15):

    12:
    13:
    14:
    15:
    16: ‘Are you sure?’, :method => :delete %>
    17:
    18:

  31. M Awais Tue, 03 May 2011 10:55:22 UTC

    No route matches {:action=>”edit”, :controller=>”admin/categories”}

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

  32. david Wed, 20 Jul 2011 03:00:24 UTC

    this is STILL such important information – not sure why it’s not in the rails guides????

  33. david Wed, 20 Jul 2011 03:01:55 UTC

    also wonder how the syntax actually works…

    its bad for rails when you see things like this that work, but no one fully understands what is going on there and why it works.

  34. Kevin Danenberg Sat, 03 Sep 2011 03:32:54 UTC

    I am also having problems with my delete link simply taking me to the Show action rather than Destroy. I tried the [:admin, user] syntax suggest above, but it does not solve the problem.

    link_to ‘Destroy’, [:admin, user], :confirm => ‘Are you sure?’, :method => :delete

    Anyone figure this out? I’m having a hard time digging for answers on this one.

  35. John Sun, 02 Oct 2011 15:15:58 UTC

    Hey Man

    I just want to say THANK YOU, THANK YOU.

    Finally someone that could help!

Comments