I need a straightforward, easy to understand answer on this one. I\'m building a user control panel for administrative users to create/edit/delete users of the system throu
As you haven't said otherwise and it looks right, I'm going to assume that clicking an "Add new #{type}" link works as it should. It also looks like you can successfully create Users. So I'm going to move on to address the problem with unsuccessful saves.
The controller renders the new template on a failed create action, but doesn't define the same instance variables as the new action. So we need to define them again. I've added them to the create method in the failure block. I've also made a subtle change to new that will make your form cleaner.
app/controllers/users_controller.rb:
def new
@user = User.new
@type = params[:type]
@roles = get_all_roles.reject{|r| r.name == @type}
@cancel = users_path
end
def create
@user = User.new(params[:user])
@assigned_roles = params[:user][:assigned_roles].select{|k,v| ! v.nil?}
if @user.save
update_user_roles(@user,roles)
if current_user.is_admin_or_root?
flash[:message] = "User \"#{@user.username}\" created."
redirect_to users_path
else
flash[:message] = "Congrats! You’re now registered, #{@user.username}!"
redirect_to app_path
end
else
@type = params[:type]
@roles = get_all_roles.reject{|r| r.name == @type}
@cancel = users_path
render :action => 'new'
end
end
However we're only part way done, with just that change in the controller we'll list the roles properly, but the type won't be assigned. So we have to modify the form_for call to pass the type parameter to the create call. We also need to change the form so it keeps roles selected after the failure. By removing type from @roles in the controller, the specified type isn't listed in the form. It's automatically applied, as a hidden_field. I've also taken the liberty of restructuring the section around the roles checkboxes, so that the %li containing the roles section only appears if there are roles to show.
app/views/users/new.html.haml
- form_for @user, :url => {:action => :create, :type => @type) do |f|
%ol{ :class => 'form' }
%li
= f.label :username
= f.text_field :username
%li
= f.label :email
= f.text_field :email
%li
= f.label :password
= f.password_field :password
%li
= f.label :password_confirmation
= f.password_field :password_confirmation
- if @roles
%li
- @assigned_roles ||= []
- @roles.each do |role|
= label_tag role
= check_box_tag 'user[assigned_roles][]', role, @assigned_roles.include?(role)
= hidden_field_tag 'user[assigned_roles][]', @type
%li{ :class => 'submit' }
= f.submit 'Register'
= link_to 'cancel', @cancel
With these quick changes things should work the way you expect.
Basically everything EmFi suggested, plus a few tweaks:
app/views/users/new.html.haml
- if @roles
%li
- @assigned_roles ||= []
- @roles.each do |role|
= label_tag role
= check_box_tag 'user[assigned_roles][]', role, (@roles & @assigned_roles ).include?(role)
removed:
= hidden_field_tag 'user[assigned_roles][]', @type
(The parameter I wanted to carry over is supplied by:
- form_for @user, :url => {:action => :create, :type => @type) do |f| ...
Since i only used it for presentation, I don't need to store it in the form.)
app/controllers/users_controller.rb:
def new
@user = User.new
@type = params[:type]
@roles = get_all_roles # don't need to reject anything here either, since the :type is no longer part of this array
@cancel = users_path
end
def create
@user = User.new(params[:user])
@assigned_roles = params[:user][:assigned_roles] # already has the roles I need; unchecked checkboxes are not passed into this; only checked ones
if @user.save
update_user_roles(@user,@assigned_roles)
if current_user.is_admin_or_root?
flash[:message] = "User \"#{@user.username}\" created."
redirect_to users_path
else
flash[:message] = "Congrats! You’re now registered, #{@user.username}!"
redirect_to app_path
end
else
@type = params[:type]
@roles = get_all_roles # don't need to reject anything, since the :type is no longer part of this array
@cancel = users_path
render :action => 'new'
end
end
Thanks, EmFi, for setting me straight on this! The @assigned_roles
logic and
- form_for @user, :url => {:action => :create, :type => @type) do |f| ...
were the keys to this puzzle I was searching for!