I setup a platform that uses Devise to create and manage users and CanCanCan to manage permissions. Users have a role (admin or client) that allows them access to certain areas. Admin users have the ability to can :manage, :all
I extended Devise so that I have a users/registrations and users/sessions controller.
Admin users have access to views in a ManagerController dashboard that allows them to manage other users. I've figured out how to show the details of a different user, but I can't figure out how to save the information. I get errors that indicate it either can't find the User or that it requires a POST route.
I'm fairly new to Rails, so it could be something simple. I was able to find solutions that included the regular Devise installation, but not the extension. I feel like the problem may be in my routes.
I also can't create new users from here either.
Routes.rb
get 'users' => 'manager#users'
get 'users/edit' => 'manager#edit'
post 'users/edit' => 'manager#edit'
get 'users/new' => 'manager#new'
devise_for :users, :controllers => { registrations: 'users/registrations', sessions: 'users/sessions' }
devise_scope :user do
authenticated :user do
root 'users/registrations#edit', as: :authenticated_root
end
unauthenticated do
root 'users/sessions#new', as: :unauthenticated_root
end
end
Manager Controller
class ManagerController < ApplicationController
authorize_resource :class => false
include ManagerHelper
def users
@users = User.where.not(:id => current_user.id)
end
def new
@user = User.new
end
def create
@user = User.new(user_params)
if @user.save
flash[:notice] = "Successfully created User."
redirect_to root_path
else
render :action => 'new'
end
end
def edit
@user = User.find(params[:id])
@companies = Company.all
end
def update
@user = User.find(params[:id])
params[:user][:id].delete(:password) if params[:user][:password].blank?
params[:user][:id].delete(:password_confirmation) if params[:user][:password].blank? and params[:user][:password_confirmation].blank?
if @user.update(user_params)
flash[:notice] = "Successfully updated User."
redirect_to root_path
else
render :action => 'edit'
end
end
end
private
def user_params
params.require(:user).permit(:email, :first_name, :last_name, :company_id, :role, :password, :password_confirmation)
end
end
ManagerHelper
module ManagerHelper
def resource_name
:user
end
def resource
@resource ||= User.new
end
def devise_mapping
@devise_mapping ||= Devise.mappings[:user]
end
end
Manager/Edit.html.erb
<h2>Edit <%= resource_name.to_s.humanize %></h2>
<%= form_for(resource, :as => @user, :url => edit_user_registration_path(resource_name)) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
<%= f.hidden_field :id %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
</div>
<div class="field">
<%= f.label :first_name %><br />
<%= f.text_field :first_name%>
</div>
<div class="field">
<%= f.label :last_name %><br />
<%= f.text_field :last_name %>
</div>
<div class="field">
<%= f.label :company %><br />
<%= f.collection_select :company_id, @companies, :id, :name, prompt: true %>
</div>
<div class="field">
<%= f.label :role %><br />
<%= f.text_field :role %>
</div>
<div class="field">
<%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
<%= f.password_field :password, autocomplete: "new-password" %>
<% if @minimum_password_length %>
<br />
<em><%= @minimum_password_length %> characters minimum</em>
<% end %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
</div>
<div class="actions">
<%= f.submit "Update" %>
</div>
<% end %>
I would like the updated information to be saved to the User database.
Currently, I get this error when I click update after changing the user info.
ActiveRecord::RecordNotFound in ManagerController#edit Couldn't find User without an ID Weirdly, when I see the User info, the url is: http://localhost:3000/users/edit?id=2 But when I update (and get the error), the url changes to: http://localhost:3000/users/edit.user
I would also like to be able to create New Users from this screen. Currently, the user form populates with the information of the user who is logged in. (To be fair, I have been trying to get the edit user correct before tackling this issue.)
Many tries later, I've found a solution. There were a lot of errors, so bear with me.
Routes.rb -- Was using the wrong URL in the form submission, so needed to add the routes for the Update function in the Manager controller.
get 'users/edit' => 'manager#edit'
post 'users/edit' => 'manager#edit'
get 'users/update' => 'manager#update'
post 'users/update' => 'manager#update'
Manager Controller -- I had to change the password rules so that I could update without a password. Similar concept, slightly different execution.
def update
@user = User.find(params[:user][:id])
@companies = Company.all
if params[:user][:password].blank? && params[:user][:password_confirmation].blank?
params[:user].delete(:password)
params[:user].delete(:password_confirmation)
end
if @user.update(user_params)
flash[:notice] = "Successfully updated User."
redirect_to root_path
else
render :action => 'edit'
end
end
Rendered Form.html.erb - Updated with newly created URL path.
<%= form_for(resource, as: @user, url: users_update_path(resource_name)) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>