I have a rails application with a custom model that can have multiple roles. I implemented this with a bitmask:
class User < ActiveRecord::Base DEFAULT_ROLES = %w[developer entrepreneur] ROLES = ['admin', 'entrepreneur', 'developer'] def has_role?(role) roles.include?(role.to_s) end def is?(role) has_role?(role) end def roles=(roles) self.roles_mask = (roles & ROLES).map { |r| 2**ROLES.index(r) }.inject(0, :+) end def roles ROLES.reject do |r| ((roles_mask.to_i || 0) & 2**ROLES.index(r)).zero? end end end
On the application registration page, I want users to choose whether they are an "entrepreneur" or a "developer." However, I want to make sure that they cannot assign themselves (or anyone else) any other role if they are no longer an administrator.
My first thought was to do this in the roles= method, changing it to look like
def roles=(roles) unless current_user.is?(:admin) validates_inclusion_of roles, :in => DEFAULT_ROLES end self.roles_mask = (roles & ROLES).map { |r| 2**ROLES.index(r) }.inject(0, :+) end
However, as I found out, you cannot access current_user from within the model (which, I think, makes sense if you think about it ...)
My next attempt was to see if I could do this using Strong options .
I expected it to look something like this (I use devise, overriding RegistrationsController)
class RegistrationsController < Devise::RegistrationsController private def sign_up_params if (user_signed_in?) && (current_user.is?(:admin)) params.require(:user).permit(:name, :school, :email, :password, :password_confirmation, {roles: User::ROLES}) else params.require(:user).permit(:name, :school, :email, :password, :password_confirmation, {roles: User::DEFAULT_ROLES}) end end def account_update_params if (user_signed_in?) && (current_user.is?(:admin)) params.require(:user).permit(:name, :school, :email, :password, :password_confirmation, :current_password, :about_me, {roles: User::ROLES}) else params.require(:user).permit(:name, :school, :email, :password, :password_confirmation, :current_password) end end end
However, when I tried this, I got the following:
which makes me think that I donโt understand how strong parameters work.
Is it possible to limit what values โโa user can enter for any given field based on this user role using strong parameters? If not, is there any other way to do this?