I have been working on Devise and I tried to find a way to add more database attributes to the users table from devise. But it seems devise supports only email and password fields.
Is it possible to add more fields to the devise, so devise can validate to and save it to the users table on create, update calls.
yes you can add more fields by using migration.
I hope below link is help full to you.
http://www.jacopretorius.net/2014/03/adding-custom-fields-to-your-devise-user-model-in-rails-4.html
Yes. Checkout their documentation. https://github.com/plataformatec/devise
and search the page for "strong parameters" that should show you mostly what you're looking for.
an example:
class ApplicationController < ActionController::Base
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit({ roles: [] }, :email, :password, :password_confirmation, :first_name, :last_name, :gender, :avatar, :latitude, :longitude ) }
devise_parameter_sanitizer.for(:account_update) { |u| u.permit({ roles: [] }, :email, :password, :password_confirmation, :current_password, :first_name, :last_name, :age, :about_me, :gender, :avatar, :latitude, :longitude ) }
end
Yes you can like below I did for first_name, last_name
class RegistrationsController < Devise::RegistrationsController
private
def sign_up_params
params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation)
end
def account_update_params
params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation, :current_password)
end
end
Related
The following console information
Started POST "/users" for
Processing by RegistrationsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"==", "user"=>{[...], "email_contact"=>"5#mail.ne", "cap"=>"", "client_retail"=>"true"}, "commit"=>"Register"}
Unpermitted parameters: :email_contact, :client_retail
is baffling, as the two unpermitted parameters (they were created subsequently to the original version, but the db was dropped, recreated and migrated) are stubbornly being ignored (while the user is getting created.
UsersController does include these attributes
def user_params
params.require(:user).permit(:email, :password, :password_confirmation, :remember_me, [...] :internal, :client_retail, :email_contact)
end
as does RegistrationsController:
private
def sign_up_params
params.require(:user).permit(:email, :password, :password_confirmation, :remember_me, [...] :internal, :client_retail, :email_contact)
end
def account_update_params
params.require(:user).permit(:email, :password, :password_confirmation, :remember_me, [...] :internal, :client_retail, :email_contact)
end
In addition, the ApplicationController invokes the sanitizer
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:email, :password, :password_confirmation, :nome, :cognome, :email_contact, :client_retail])
devise_parameter_sanitizer.permit(:sign_in, keys: [:login, :password, :password_confirmation])
devise_parameter_sanitizer.permit(:account_update, keys: [:email, :password, :password_confirmation, :current_password])
end
Oddly, those two attributes will get processed under the update action, although not listed in the sanitizer.
How can these parameters be allowed?
Rename your controller to Users::RegistrationsController < Devise::RegistrationsController or RegistrationsController < Devise::RegistrationsController depending on where your custom RegistrationsController is located.
This question already has answers here:
Add Custom Field/Column to Devise with Rails 4
(4 answers)
Closed 6 years ago.
I want to add a property name in the user model. I ran the migration command to add the column to the database and that worked. Adding the property to user itself worked as well but it isn't saved in the db.
How can I add the property "name" to the required params of the sign_up and account_update of RegistrationController?
This is my user model
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessor :name
end
I tried adding the required params to the methodes like this in the RegistrationController
class Users::RegistrationsController < Devise::RegistrationsController
def sign_up_params
params.require(:user).permit(:name,:email, :password, :password_confirmation)
end
def account_update_params
params.require(:user).permit(:name, :email, :password, :password_confirmation, :current_password)
end
end
In the routings i added the line
devise_for :users, controllers: { registrations: 'users/registrations' }
But the name of the user still isn't saved in the database.
Add this to your ApplicationController to configure signup signin & account_update params.
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:name,:email, :password, :password_confirmation) }
devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:login, :username, :email, :password, :remember_me) }
devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:name, :username, :anonymous, :email, :password, :password_confirmation,:reset_password_token) }
end
And also add before_filter to ApplicationController like :
before_filter :configure_permitted_parameters, if: :devise_controller?
Please check Devise Parameter Sanitization
You can try this:
class Users::RegistrationsController < Devise::RegistrationsController
def sign_up_params
devise_parameter_sanitizer.for(:sign_up).push(:name)
end
def account_update_params
devise_parameter_sanitizer.for(:account_update).push(:name, :email, :password, :password_confirmation, :current_password)
end
end
I have a rails app with a user model, which is able to have several roles. I implemented this using a bitmask like this:
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
In the signup page for the app, I want users to choose if they are an 'entrepreneur' or a 'developer'. However, I want to ensure that they are not able assign themselves (or anyone else) any other role, unless they are already an admin.
My first thought was to do this in the roles= method by changin 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 can't access current_user from inside a model (which I guess makes sense if you think about it...)
My next attempt was to see if I could do this using Strong Parameters.
I was expecting it would look something like this (I'm using devise, overriding the 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 that, I got this:
which makes me think I'm misunderstanding how Strong Parameters really works.
Is it possible to restrict what values a user can enter for any given field based on that users's role with Strong Parameters? If not, is there a different way to accomplish this?
I figured it out, here's how I did it. (This is the method overrides Devise's RegistrationController, if you're not using devise, then simply replace whatever method controls what parameters are entered into a new user.)
class RegistrationsController < Devise::RegistrationsController
private
def sign_up_params
parameters = params.require(:user).permit(:name, :school, :email, :password, :password_confirmation, :about_me, roles: [])
unless (user_signed_in?) && (current_user.is?(:admin))
parameters[:roles] = parameters[:roles].reject { |h| !User::DEFAULT_ROLES.include? h }
parameters
end
end
def account_update_params
if can? :assign_roles, :all
params.require(:user).permit(:name, :school, :email, :password, :password_confirmation, :current_password, :about_me, roles: [])
else
params.require(:user).permit(:name, :school, :email, :password, :password_confirmation, :current_password)
end
end
end
I just filtered out the parameter in parameters[:roles] to only include values that were contained in User::DEFAULT_ROLES (shown above in the question), and then returned the parameters object.
My registrations are working properly, I have 3 custom fields: name, avatar, avatar_cache.
Only the :name custom field is giving me a:
Unpermitted parameters: name in console.
I already sanitized strong parameters in Application Controller and the avatar / avatar_cache are saving correctly. Am I missing something?
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:name, :avatar, :avatar_cache, :email, :password, :password_confirmation) }
end
def configure_permitted_parameters
devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:name, :avatar, :avatar_cache, :email, :password, :current_password, :password_confirmation) }
end
Currently, you have redefined the method configure_permitted_parameters, which is why Ruby is picking the latest method definition i.e., the one which whitelists attributes for account_update. So, when you try to sign_up with custom attribute name, you would receive
Unpermitted parameters: name warning
as because of the overwriting the method configure_permitted_parameters, devise has no idea about the custom attributes that should have been whitelisted for sign_up
Your configure_permitted_parameters method should look like:
class ApplicationController < ActionController::Base
before_filter :configure_permitted_parameters, if: :devise_controller?
## ...
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:name, :avatar, :avatar_cache, :email, :password, :password_confirmation) }
devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:name, :avatar, :avatar_cache, :email, :password, :current_password, :password_confirmation) }
end
end
I have the model Agency based on Devise:
class Agency < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :name, :email, :phone, :address, :city, :state, :zip,
:notes, :is_admin, :password, :password_confirmation, :remember_me
protected
def password_required?
!persisted? || password.present? || password_confirmation.present?
end
end
Also I have the AgenciesController based on active_scaffold:
class Admin::AgenciesController < Admin::BaseController
before_filter :authorize_admin!
active_scaffold :agency do |conf|
actions.exclude :show
create.link.page = true
update.link.page = true
list.columns = [
:name, :email, :phone, :address, :city,
:state, :zip, :notes, :events, :is_admin
]
create.columns = [
:name, :email, :phone, :address, :city, :state, :zip,
:is_admin, :password, :password_confirmation
]
update.columns = [
:name, :email, :phone, :address, :city, :state, :zip,
:is_admin, :password, :password_confirmation
]
columns.add :password
columns.add :password_confirmation
columns[:password].form_ui = :password
columns[:password_confirmation].form_ui = :password
end
end
Then here is Agency update form:
I would like to provide an opportunity for user to omit filling in of password and password_confirmation fields. But if user fills in password field the password_confirmation field have to be required.
I almost solved my problem by password_required? method. But javascript required verification on client doesn't allow me solve my problem completely.
How Can I remove JS varification from client for password and password_confirmation fields?
Try:
validates_confirmation_of :password, :if => :password_required?
validates :password_confirmation, :presence => true, :if => '!password.nil?'
Note that the validation is only triggered if password_required? returns true, and password_required? will return false if the password_confirmation field is nil.
So in order to make password_confirmation field to be nil, you simply need to remove the password_confirmation field from the form and that way you will always get it nil thus bypassing the validations.
Alternate Solutions:
1) Skip validation of password field
2) Just save a random secure generated number in the password field ( Better because it's easy and also maintain the consistency ).
self.password = self.password_confirmation = SecureRandom.urlsafe_base64(n=6)
Also if you want that such fields should be identified differently as been left by the user then you can give unique passwords to them so later you impose the condition like:
if(self.password == "something unique" and self.password_confirmation == "something unique")
flash[:notice] = "The user has not password"
end
Then on UI level, you simply display with blank using the above condition.
#Saurabh Jain, thanks a lot for your advices.
But solution was so much simple.
I have found out that active_scaffold adds an required attribute for input tag of password field.
By another words a client gets an html
<input type="password" required="required" size="30" name="record[password_confirmation]" id="record_password_confirmation_4" class="password_confirmation-input text-input" autocomplete="off">
Exactly required attribute was my problem :) To remove it from html simply add line
columns[:password].required = false;
to active_scaffold configuration in Admin::AgenciesController (see it above)