Firstly here is my ruby and rails version with a couple of the important gem versions.
- Ruby 1.9.3-p125
- Rails 3.2.2
- Devise 2.0.4
- CanCan 1.6.7
I used the template from Daniel Kehoe to get the project up and running quickly.
$ rails new myapp -m https://raw.github.com/RailsApps/rails3-application-templates/master/rails3-devise-rspec-cucumber-template.rb -T
My problem:
I have an administration section for creating new users and two roles with this ability. I have a requirement, admin users should not be able to create superadmin users.
When an admin logs in and clicks on the new user button the roles list is filtered to remove the superadmin option, if I logout of the admin role and login as a superadmin then create a user I have the filtered list from the admin. If I refresh 5-6 times I get the correctly filtered list.
User model
# /app/models/user.rb
class User < ActiveRecord::Base
ROLES = {
superadmin: 'superadmin',
admin: 'admin'
}
def role?(role)
self.role == role.to_s
end
end
User controller
# /app/controllers/admin/users_controller.rb
module Admin
class UsersController < BaseController
load_and_authorize_resource
def new
@user = User.new
@roles = User::ROLES
if current_user.role? :admin
@roles.delete :superadmin
end
end
end
end
View
# /app/views/admin/users/_form.html.haml
= form_for [:admin, @user], html: { class: 'form-horizontal' } do |f|
...
.control-group
= f.label :role, class: 'control-label'
.controls
= f.select :role, @roles, selected: :admin
If anyone can point me in the right direction as to why the @roles is retaining its value between login/logouts for users with different roles but then being cleared that would be really helpful thanks, I’ve been stumped on this for over an hour as has a few others.
the line
@roles = User::ROLESis getting a reference to User::ROLES instead of a copy. So, when you call@roles.delete :superadmin, you’re modifying User::ROLES, too.I’m guessing after 5-6 requests, your request is served by a different process whose global copy has not (yet) been modified.
To solve the provlem, change
@roles = User::ROLESto@roles = User::ROLES.dupOr, change
@roles.delete :superadminto@roles = @roles.except(:superadmin)