Adding role's field to users

Hi,

(Using Rails 4.0.1, Ruby 1.9.3, latest devise and cancan gems. sqlite db
for local development)

I am a rookie, setting up website and was adding roles(using cancan gem)
to
my users table. Everything works great, except when I select a role for
a
user it is not getting saved. The user gets saved/created OK but it
never
updates/ remembers any roles assigned to the user.

I was following the advice given here(Many roles per user). Any help or
advice is most appreciated…

https://github.com/ryanb/cancan/wiki/role-based-authorization

Here is my users form…

<%= form_for(@user) do |f| %>

<%= f.label :email %>
<%= f.text_field :email %>
<% if @current_method == "new" %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation %>
<% end %> <% for role in User::ROLES %> <%= check_box_tag "user[roles][#{role}]", role, @user.roles.include?(role), {:name => "user[roles][]"}%> <%= label_tag "user_roles_#{role}", role.humanize %>
<% end %> <%= hidden_field_tag "user[roles][]", "" %>
<%= f.submit %>
<% end %>

/app/model/user.rb

class User < ActiveRecord::Base

ROLES = %w[admin blog_author]

def roles=(roles)
self.roles_mask = (roles & ROLES).map { |r| 2**ROLES.index®
}.inject(0, :+)
end

def roles
ROLES.reject do |r|
((roles_mask.to_i || 0) & 2**ROLES.index®).zero?
end
end

def is?(role)
roles.include?(role.to_s)
end

Include default devise modules. Others available are:

:confirmable, :lockable, :timeoutable and :omniauthable

devise :database_authenticatable, :registerable, :recoverable,
:rememberable, :trackable, :validatable
end

On Nov 18, 2013, at 2:03 PM, Phillip wrote:

Hi,

(Using Rails 4.0.1, Ruby 1.9.3, latest devise and cancan gems. sqlite db for
local development)

Just a guess here – have you updated your strong parameters declaration
in the users_controller to include the roles field?

Walter

Hi Walter,

Thanks for reply.

Yes I have added in roles, but perhaps I am doing it wrong? Here is my
users controller for creating and updating…

def create
@user = User.new(params[:user].permit(:email, :password, :roles))
# authorize! :manage, @users

respond_to do |format|
  if @user.save
    format.html { redirect_to(@user, :notice => 'User was 

successfully
created.’) }
format.xml { render :xml => @user, :status => :created,
:location
=> @user }
else
format.html { render :action => “new” }
format.xml { render :xml => @user.errors, :status =>
:unprocessable_entity }
end
end
end

PUT /users/1

PUT /users/1.xml

def update
@user = User.find(params[:id])

respond_to do |format|
  if @user.update(params[:user].permit(:email, :password, :roles))
    format.html { redirect_to(@user, :notice => 'User was 

successfully
updated.’) }
format.xml { head :ok }
else
format.html { render :action => “edit” }
format.xml { render :xml => @user.errors, :status =>
:unprocessable_entity }
end
end
end

Also, watch your console as you update, and see if there’s a warning
about illegal attributes not being saved.

Walter

Aha. You have a method called roles, but you’re storing this in
roles_mask? Which is a string? You should try adding roles_mask in the
strong parameters, I think.

Walter

Ah yes, in console I have a line(when creating a user) saying…

Unpermitted parameters: password_confirmation, roles

I tried…

def create
@user = User.new(params[:user].permit(:id, :email, :password,
:roles_mask))
…etc…

and…

def create
@user = User.new(params[:user].permit(:id, :email, :password,
:roles_mask[:roles]))

and…

def create
@user = User.new(params[:user].permit(:id, :email, :password,
:roles))

But none save the roles. The roles_mask col in the users table is an
integer. It explains the process in the link mentioned on my first post.
Using a “bitmask”.

Okay, try this (just to see if it saves at all):

params[:user].permit!

That turns off strong parameters entirely, so let’s see if your value is
getting saved.

Walter

Yes! That works. Thanks Walter.

(code now…)
def create
@user = User.new(params[:user].permit!)

Just the users table, “role_mask” the one we want? Here is the users
from
schema.rb

create_table “users”, force: true do |t|
t.string “email”, default: “”, null: false
t.string “encrypted_password”, default: “”, null: false
t.string “reset_password_token”
t.datetime “reset_password_sent_at”
t.datetime “remember_created_at”
t.integer “sign_in_count”, default: 0, null: false
t.datetime “current_sign_in_at”
t.datetime “last_sign_in_at”
t.string “current_sign_in_ip”
t.string “last_sign_in_ip”
t.datetime “created_at”
t.datetime “updated_at”
t.integer “roles_mask”
end

Okay, so now you know that strong parameters is the problem. Go into
your schema, copy the entire table definition, and paste it here. This
will be easy to fix, just have to see what the actual column name is
that you need to whitelist.

Don’t just leave your controller like this, you are not safe.

Walter

Okay, try this:

@user = User.new(params[:user].permit(:id, :email, :password, 

:password_confirmation, :roles))

And if that doesn’t do it, then I need to see the raw parameters from
your form submission (they will be in your console).

Walter

Hi Phillip,

If your roles param is an array, you should tell strong parameters
explicitly like this:

params[:user].permit(:id, :email, :password, :roles => [])

Excepted from the doc:

To declare that the value in params must be an array of permitted
scalar values map the key to an empty array:

params.permit(:id => [])

Yes that has it working now! The world is beautiful again.

Walter, Derrick, I can get phase one up and running thanks to this.
Thanks
a million guys!

On Tuesday, November 19, 2013 3:00:35 PM UTC, Walter Lee D. wrote:

It looked to me as though he was saving it as a bit mask, though. Does the
strong parameters apply when accepting the input or saving to the
persistence layer?

Strong parameters filter the input before it hits the model object - how
you persist it is irrelevant.

Fred

It looked to me as though he was saving it as a bit mask, though. Does
the strong parameters apply when accepting the input or saving to the
persistence layer?

Walter

On Nov 20, 2013, at 10:27 AM, Frederick C. wrote:

On Tuesday, November 19, 2013 3:00:35 PM UTC, Walter Lee D. wrote:
It looked to me as though he was saving it as a bit mask, though. Does the
strong parameters apply when accepting the input or saving to the persistence
layer?

Strong parameters filter the input before it hits the model object - how you
persist it is irrelevant.

Fred

Thanks! That clears up a lingering question for me.

Walter

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs