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.
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..
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).
Awesome!
Thank you
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
I don’t think that there another way. That’s the only way to reference namespaced controller.
Good trick Slobo! Sadly there’s no other way.
Thank you so much. Exactly the information I needed, not that pretty but now I can do what I want to achieve.
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” )
[...] 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 [...]
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!
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
…arrrgh, the code got cut out. Here’s the problematic code:
‘Are you sure?’, :method => :delete %>
…[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
Do you think it’d be possible for you to teach us how to password protect the admin namespace?
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
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
@Daniel the destroy link should use the [:admin, user] notation.
link_to ‘Destroy’, [:admin, theme], :confirm => ‘Are you sure?’, :method => :delete
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.
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.
@Ankit The whole point is to have one model which is used for both frontend and admin controllers.
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?
@Reinaldo As far as I know there’s no option to generate scaffold specifically for certain namespace.
@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?
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!
Thanks, the changes to fix the scaffolding were just what I needed.
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
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
ml => @email_notification, :status => :created, :location => @email_notification }
You should change it to say
ml => @email_notification, :status => :created, :location => [:admin, @email_notification] }
format.xml { render
[...] Admin namespace我是照這篇做的,做了看版管理及文章管理。就一般論壇而言,像「看版管理」這種東西,一般人不會有新增、修改、刪除的權限(版主可能有修改),所以scaffold架出來的東西應該的確比較適合移到admin去,而給使用者的邏輯再手動打造。但我的實作有種不夠DRY的感覺,把view和controller的code複置兩份,感覺不太好。可以想見,其實可以利用繼承、共用函式等方式,將程式碼變的更精簡。這部份有更好的best practice嗎? ( 6)用 Rake 撰寫自動化步驟,生假資料。寫一個 rake 可以達成以下步驟:「砍 db => 建 db => 跑 migration => 生種子資料」,另一個 rake 是生假文章與假論壇。 [...]
Thanks!!! That’s what I was looking for
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:
No route matches {:action=>”edit”, :controller=>”admin/categories”}
‘Are you sure?’, :method => :delete %>
this is STILL such important information – not sure why it’s not in the rails guides????
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.
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.
Hey Man
I just want to say THANK YOU, THANK YOU.
Finally someone that could help!