I'm trying to create custom form that allows admins to toggle the user privileges of users on and off, and save them to the database. I must be doing something completely wrong, because the pages generate fine, and the submit button submits to the action fine, but nothing gets saved to the database, and it just renders my initial view again. Can anyone see what I'm doing wrong?
The Code
Routes:
resources :users do
member do
get 'assign'
put 'assign_update'
end
end
...
Controller (This weird way of doing it is an attempt to circumvent the fact that the admin and other attributes are not accessible. It might be a mess.):
...
def assign
@user = User.find(params[:id])
end
def assign_update
admin_protected = params[:user].delete(:admin)
@user = User.find(params[:id])
@user.admin = admin_protected
if @user.save
flash[:success] = "User updated"
redirect_to users_path
else
render 'assign'
end
end
View:
...
<%= form_for(@user, url: { controller: 'users',
action: 'assign_update'}, method: 'put') do |f| %>
<%= f.label :admin, 'Is admin?', class: 'checkbox inline' %>
<%= f.check_box :admin %>
<%= f.submit "Save changes", class: "btn btn-large btn-primary" %>
<% end %>
So to summarize the conversation we had in the comment section under the question...
Problem was found to be validations on other user model attributes. The user instance couldn't be saved because validations were not passing when save
method was being executed. As a result, Rails was just rendering assign view.
update_attribute
method updates an attribute without model validation nor mass assignment protection. And admin
attribute fits those two criteria in this case.
You should be using attr_accessible in your model and manually picking those fields from the params has and assigning them individually making sure that the admin field is NOT included in the list of fields assigned to the attr_accessible declaration
So
def assign_update
admin_protected = params[:user].delete(:admin)
@user = User.find(params[:id])
@user.admin = admin_protected
if @user.save
flash[:success] = "User updated"
redirect_to users_path
else
render 'assign'
end
end
becomes
def assign_update
# admin_protected = params[:user].delete(:admin)
@user = User.find(params[:id])
@user.admin = params[:user][:admin]
if @user.save
flash[:success] = "User updated"
redirect_to users_path
else
render 'assign'
end
end
The problem is that in your approach you are still mass assigning.
To debug what is actually happening you should take a careful look at you log file output
UPDATE
Check the errors list. Add the following to your form
<% if @user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@user.errors.count, "error") %> prohibited this account from being saved:</h2>
<ul>
<% @user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
It should give you, ad your users a clearer idea of what is wrong and how to fix it
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.