4

I am working on an app where a company admin should be able to create and update users in his company. (Users can also create and update their accounts independently).

I used Devise and Cancan for registration and permission management. I configured Devise to get the required signup and user update processes. I created a namespace for the admin views.

My admin controller (/app/controllers/admin/base_controller.rb) looks like this:

class Admin::BaseController < ApplicationController
  authorize_resource :class => false
  layout 'admin'

  def dashboard
  end
end

In addition to my "regular" users_controller, I have a controller (/app/controllers/admin/users_controller.rb) and associated views dedicated to Admin user management.

class Admin::UsersController < Admin::BaseController
  ...
end

Now, what's the cleanest way to implement Devise-related user admin features (at this point, create and update users)?

  1. Have a conditional (based on user permissions) in my "regular" registrations_controller and confirmations_controller to render and redirect different views? (cf. Devise form within a different controller)

  2. Or create new controllers in my admin namespace? If the latest is better, what are the main steps to follow?

Community
  • 1
  • 1
alex
  • 1,882
  • 3
  • 22
  • 32

1 Answers1

1

Herein lies your issue, once you namespace or move any user management to another controller, you leave the scope of Devise. So at the point where you are in Admin::UsersController, Devise doesn't care about what you do, there are no 'devise-related' admin features as you stated. You can implement your Admin::UsersController as a standard RESTful controller if you wish.

In this manner, creating users through a namespaced controller, Devise will still perform actions such as confirmations. There is one small thing to keep in mind when creating and updating users this way. If you do not set a password as the admin, you will have to delete the password and password_confirmation from the params hash. To do so, the start of your create and update actions would look like so:

if params[:user][:password].blank?
  params[:user].delete(:password)
  params[:user].delete(:password_confirmation)
end

I employ this same method in many of my applications, and have yet to have it fail.

EDIT

namespace :admin do
  resources :users
end
janders223
  • 2,995
  • 2
  • 19
  • 27
  • Thanks for the explanation! Can you explain what the routes would look like in this case? – alex Dec 30 '12 at 05:14
  • @alex, I added to my answer to what the routes would look like. – janders223 Dec 30 '12 at 13:48
  • I declared my admin/users_controller as "class Admin::UsersController < RegistrationsController", added "resources :users" under my admin namespace in routes.rb (which gives me access to new_admin_user and edit_admin_user routes), but when I visit /manage/users I got an error message: "1) You forgot to wrap your route inside the scope block. For example: devise_scope :user do match "/some/route" => "some_devise_controller" end 2) You are testing a Devise controller bypassing the router." What's missing here? – alex Dec 31 '12 at 22:17
  • I added get "'/manage/users' => 'admin/users#index'" and "get 'manage/users/new' => 'admin/users#new'" under "devise_scope :user do", but find it strange that I have to add a route for each action... any cleaner way to make it work? – alex Dec 31 '12 at 22:49
  • You shouldn't be inheriting from `Devise::RegistrationsController`, just `ActionController::Base`. You don't need Devise at all in this situation, you are just managing users through standard RESTful actions. – janders223 Dec 31 '12 at 23:21
  • Not sure I was clear: when the company admin adds a user, the user then goes through the "regular" confirmation process (receives confirmation email then goes to page and confirms account with name and password). I need Devise for that, don't I? – alex Dec 31 '12 at 23:44
  • Devise adds an `after_create` callback to send the confirmation email to your user model, https://github.com/plataformatec/devise/blob/master/lib/devise/models/confirmable.rb#L37. Anytime a user is created the callback will be fired, sending the confirmation email. I have code working in several applications employing the methods I am talking about, and it works just as you are wanting it to. – janders223 Dec 31 '12 at 23:48
  • thanks for your reply and patience, and yes, it works! Now, the only remaining problem is that validations don't work. My form for creating users looks like: " resource_name, :url => registration_path(resource_name), :html => { :method => :post, :class => "form-horizontal" }) do |f| %>" and I added the helper methods (http://stackoverflow.com/questions/4081744/devise-form-within-a-different-controller). But when I enter an invalid or no email address records are still created. I don't understand why! – alex Jan 01 '13 at 00:23
  • Again, Devise has no business here. Your form needs to be, ``, more info on namespaced forms, http://guides.rubyonrails.org/form_helpers.html#relying-on-record-identification. As for the validations, again Devise is completely out of the picture, you will need to handle validations yourself on your model. – janders223 Jan 01 '13 at 03:19