Pregunta

With my set up I have 2 types of Devise users Admins and Users I would like to be able to have the admins manage the users.

I have found some tutorials about this but they approach the problem from the perspective of a single User model with roles.

So far I've gotten to the point where, when I'm logged in as an admin, I can list the users, destroy the users and create new users, however, when I try to edit a user I get a blank form (as opposed to one that's populated by user information)

Any advice would be appreciated.

Below are the relevant files. Let me know if you need to see anything else.

/config/routes.rb

TestApp::Application.routes.draw do
  devise_for :admins
  devise_for :users


  root              to: 'pages#home'

  # Admin Routes
  if Rails.env.production?
    devise_for :admins, :skip => [:registrations]
  else
    devise_for :admins
  end

  namespace :admins do
    resources :users
  end

  authenticated :admin do
    # For production because of skip registrations
    get     'admins/edit'              => 'devise/registrations#edit',        as: :edit_admin_registration
    put     'admins'                   => 'devise/registrations#update',      as: :admin_registration

    get     'admins/dashboard'         => 'admins#dashboard',                 as: :admin_dashboard

    devise_scope :admin do
      get     'admins/list'            => 'admins/users#index',               as: :manage_users
      get     'admins/users/new'       => 'admins/users#new',                 as: :new_admins_user
      get     'admins/users/:id/edit'  => 'admins/users#edit',                as: :edit_admins_user
      post    'admins/users'           => 'admins/users#create',              as: :users
      delete  'admins/users/:id'       => 'admins/users#destroy',             as: :destroy_admins_user
    end

    # Manage Content Routes
    get     '/pages/manage'            => 'pages#manage',                     as: :manage_pages
    get     '/products/manage'         => 'products#manage',                  as: :manage_products
  end

  authenticated :user, :admin do
    get     '/products'                => 'products#index'
    get     '/pages/4'                 => 'products#index'
    get     '/gallery'                 => 'products#index'
  end

  unauthenticated do
    devise_scope :users do
      get   '/pages/4'                 => 'devise/registrations#new'
      get   '/gallery'                 => 'devise/registrations#new'
    end
  end

  resources :pages
  resources :products

end

/controllers/admins_controller.rb

class AdminsController < ApplicationController
  load_and_authorize_resource

  def dashboard
    render "admins/dashboard"
  end

  def index
    respond_to do |format|
      format.html
    end
  end

  def destroy
    @admin.destroy
    redirect_to manage_admins_path
  end
end

/controllers/admins/users_controller.rb

class Admins::UsersController < ApplicationController
  load_and_authorize_resource

  def index
    @users = User.all

    respond_to do |format|
      format.html
    end
  end

  def new
    @resource = User.new

    respond_to do |format|
      format.html
    end
  end

  def edit
    @user = User.find(params[:id])
  end

  def create
    @user = User.new(params[:user])

    respond_to do |format|
      if @user.save
        format.html { redirect_to manage_users_path, notice: 'User was successfully created.' }
      else
        format.html { render new_admin_user_path }
      end
    end
  end

  def update
    @user = User.find(params[:id])

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

    respond_to do |format|
      if @user.update_attributes(params[:user])
        format.html { redirect_to manage_users_path, notice: 'User was successfully updated.' }
      else
        format.html { render action: "edit" }
      end
    end
  end

  def destroy
    @user = User.find(params[:id])
    @user.destroy
    redirect_to manage_users_path
  end

  # private
  #   def check_permissions
  #     authorize! :create, resource
  #   end
end

/views/admins/users/edit.html.haml

.input-form
  %h2
    Edit #{resource_name.to_s.humanize}

  = form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| 
    = devise_error_messages! 

    %fieldset{id: "edit-your-account"}
      .field.required
        = f.label :first_name 
        = f.text_field :first_name, :autofocus => true 

      .field.required
        = f.label :last_name 
        = f.text_field :last_name

      .field.required
        = f.label :company 
        = f.text_field :company

      .field.required
        = f.label :phone 
        = f.text_field :phone

      .field.required
        = f.label :email 
        = f.email_field :email

      .field.required
        = f.label :password 
        = f.password_field :password
        %span.instructions 
          (leave blank if you don't want to change it)
          - if devise_mapping.confirmable? && resource.pending_reconfirmation? 
            %br
              Currently waiting confirmation for: 
              = resource.unconfirmed_email

      .field.required
        = f.label :password_confirmation 
        = f.password_field :password_confirmation

      .field.required
        = f.label :current_password
        = f.password_field :current_password
        %span.instructions 
          (we need your current password to confirm your changes)

      .field
        = f.submit "Update"

  = link_to "Back", :back 

/helpers/admins_helper.rb

module AdminsHelper

  # Devise helpers for Admin::UsersController
  def resource_name
    :user
  end

  def resource
    @resource ||= User.new
  end

  def devise_mapping
    @devise_mapping ||= Devise.mappings[:user]
  end
end
¿Fue útil?

Solución

Looks like renaming your instance variable should do the trick. Your edit template passes the object resource to the form but the object you've loaded from the database is set to @user:

# Admins::UsersController
def edit
  @user = User.find(params[:id])
end

# AdminsHelper
def resource
  @resource ||= User.new
end

You could pass this instance variable to the form_for instead, or rename @user as @resource so the helper method will return the proper instance.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top