Updated checkbox, when there is no data passed. ROR. What is going on?
I constructed a Many-to-Many association between Users and Roles.
When a non-administrator logs in, I have hidden the Edit Role function, using
using the following code:
view/users/edit.html.erb
<%= error_messages_for :user %>
<% form_for @user do |f| -%>
<p><label for="login">Login</label><br/>
<%= f.text_field :login %></p>
<p><label for="email">Email</label><br/>
<%= f.text_field :email %></p>
<p><label for="password">Password</label><br/>
<%= f.password_field :password %></p>
<p><label for="password_confirmation">Confirm Password</label><br/>
<%= f.password_field :password_confirmation %></p>
<% if admin? %>
<% for role in Role.find(:all) %>
<div>
<%= check_box_tag "user[role_ids][]", role.id, @user.roles.include?(role) %>
<%= role.name %>
</div>
<% end %>
<% else %>
<% hidden_field :email, :email %>
<% end %>
<p><%= submit_tag 'Update' %></p>
<% end %>
the terminal output, was what I expected and is as follows:
Processing UsersController#update (for 127.0.0.1 at 2010-01-05 21:28:54) [PUT]
Parameters: {"commit"=>"Update", "action"=>"update", "_method"=>"put", "authenticity_token"=>"E6qUNM3gS9OmxuAZpmF7FE2Mr/lowznNLMd6ENNT6uk=", "id"=>"5", "controller"=>"users", "user"=>{"password_confirmation"=>"[FILTERED]", "password"=>"[FILTERED]", "login"=>"lesa", "email"=>"lesa@gmail.com"}}
However when I was surprised the user lost her rights (prior to her password update her roles: [1,2])
>> user = User.find_by_login("lesa")
=> #<User id: 5, login: "lesa", email: "lesa@gmail.com", crypted_password: "58026ae120d0686196df3c72c9e3df5da596326d", salt: "f02ef9e00d16f1b9f82dfcc488fdf96bf5aab4a8", created_at: "2009-12-29 15:15:51", updated_at: "2010-01-05 21:28:54", remember_token: nil, remember_token_expires_at: nil>
>> user.role_ids
=> []
>>
In the user model controller I am using:
attr_accessible :login, :email, :password, :password_confirmation, :role_ids
How would it be possible for users without the proper rights (role) to NOT update their role_ids? Obviously what I have is seriously flawed. Below is the terminal output of an Administrator correcting Lesa's Rights (role).
Processing UsersController#update (for 127.0.0.1 at 2010-01-05 21:34:01) [PUT]
Parameters: {"commit"=>"Update", "action"=>"update", "_method"=>"put", "authenticity_token"=>"/yC1s9T8yWZH+eM5fnhPwdeHPCTcT1d8IGoIn+tEd4Q=", "id"=>"5", "controller"=>"users", "user"=>{"password_confirmation"=>"[FILTERED]", "role_ids"=>["2"], "password"=>"[FILTERED]", "login"=>"lesa", "email"=>"lesa@gmail.com"}}
User controller code:
class UsersController < ApplicationController
# Be sure to include AuthenticationSystem in Application Controller instead
#routine that is excecuted before every action in controller "Before_filter
before_filter :login_required
require_role "admin", :for => [:index, :create, :destroy]
def index
@users = User.find(:all)
end
def show
@user = User.find(params[:id])
end
def destroy
@user = User.find(params[:id])
@user.destroy
redirect_to(users_url)
end
def edit
@user = User.find(params[:id])
end
def update
@user = User.find(params[:id])
params[:user][:role_ids] ||= []
if @user.update_attributes(params[:user])
flash[:notice] = 'User was successfully updated.'
redirect_开发者_高级运维to(user_path(@user))
else
render :action => 'edit'
end
end
# render new.rhtml
def new
end
def create
cookies.delete :auth_token
# protects against session fixation attacks, wreaks havoc with
# request forgery protection.
# uncomment at your own risk
# reset_session
@user = User.new(params[:user])
@user.save
if @user.errors.empty?
self.current_user = @user
redirect_back_or_default('/')
flash[:notice] = "Thanks for signing up!"
else
render :action => 'new'
end
end
end
are there any callbacks in the model? are you sure the roles existed before you updated? have you tried using accepts_nested_attributes_for :roles
in the User model? I'd have loved to see your controller code too.
Updated Your User#update action sets this to an empty array if nothing comes.... not ideal dude, as only admins will update them, and all other update requests get set as, well, nothing as you found out. scrap it. Use accepts_nested_attributes_for the roles and somehow lock out who can update them...
Of course!
I Eliminated this code from my controller: params[:user][:role_ids] ||= []
to solve this issue.
精彩评论