rails - devise strong parameters is always unpermitted for registration - ruby-on-rails

I want to permit :full_name parameter for my user model registration in devise, and I always getting Unpermitted parameter: :full_name as response for Users::RegistrationsController#create action
I have tried several ways as I show you next:
1. Application controller (option 1)
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
case params[:action]
when 'create'
devise_parameter_sanitizer.permit(:sign_up, keys: %i[full_name])
when 'update'
...
end
end
end
Result => Unpermitted parameter: :full_name
2. Registration controller (option 2)
class Users::RegistrationsController < Devise::RegistrationsController
before_action :configure_sign_up_params, only: :create
protected
def configure_sign_up_params
params.require(:user).permit(%i[full_name])
end
end
Result => Unpermitted parameter: :full_name
3. Registration controller (option 3)
class Users::RegistrationsController < Devise::RegistrationsController
before_action :configure_sign_up_params, only: :create
protected
def configure_sign_up_params
devise_parameter_sanitizer.permit(:sign_up, keys: %i[full_name ])
end
end
Result => Unpermitted parameter: :full_name
In my gemfile:
gem 'devise', '~> 4.8'
In my routes:
devise_controllers = {
confirmations: 'users/confirmations',
registrations: 'users/registrations',
invitations: 'users/invitations',
}
devise_for :users, controllers: devise_controllers
I have read devise strong params but to be honest I do not know what I am doing wrong.
Also I tried to debug in Users::RegistrationsController#create what is happening with:
def create
super do
binding.pry
end
end
but it skips the debugger breakpoint... do you have any idea what is going on?
Cheers!
Edit:
Following suggestion from JohnP, I only left :full_name in devise keys parametter sanitizer for sign_up
Also I removed a callback that is bypassing my debug breakpoint and now I can stop with pry in create action

Generally, you write strong params for a specific controller, not in your ApplicationController, because the permitted conditions will be different for each model. When using devise_parameter_sanitizer, you only need to include the extra fields you're adding - this isn't setting up your strong params from scratch, just adding keys to the default Devise list.
So, you should find that this is all you need in your Users::RegistrationsController.
def configure_sign_up_params
devise_parameter_sanitizer.permit(:sign_up, keys: [:full_name])
end
(BTW, ensure you refer to the parameter correctly, as params[:user][:full_name].)
(Oh, and if you want to do debugging, I'd suggest installing the byebug gem. You just add an extra line byebug where you want to have a breakpoint.)

Related

Devise - overriding ParameterSanitizer

I am attempting to configure a different Devise strong parameter sanitizer per model following the instructions at; https://github.com/plataformatec/devise#strong-parameters
I have created a new file named parameter_sanitizer within my Employer model directory;
app/controllers/Employers/paramater_sanitizer.rb
class Employer::ParameterSanitizer < Devise::ParameterSanitizer
def initialize(*)
super
devise_parameter_sanitizer.permit(:sign_up, keys: [:forename, :surname, :username)
end
end
Within my application controller I have;
require 'employers/parameter_sanitizer'
class ApplicationController < ActionController::Base
before_filter :devise_parameter_sanitizer, if: :devise_controller?
protect_from_forgery with: :exception
protected
def devise_parameter_sanitizer
if resource_class == Employer
Employer::ParameterSanitizer.new(Employer, :employer, params)
else
super # Use the default one
end
end
end
The error I get from signing up an Employer object is;
NameError in Devise::ConfirmationsController#show
undefined local variable or method `devise_parameter_sanitizer' for #
Any advice on how to overcome this?
Thanks,
Mark
In this initialize method you save the params as an instance variables #params so in your method you should do:
class Employer::ParameterSanitizer < Devise::ParameterSanitizer
def initialize(*)
super
#params.permit(:sign_up, keys: [:forename, :surname, :username])
end
also I believe this should work without specifying #params
Explanation
to find the solution to this problem check the devise api to better understand the methods you are calling and read the `Devise::ParameterSanitizer source code
I am quoting their ruby-rocs about the #permit() method
Instance Method Details
#permit(action, keys: nil, except: nil, &block) ⇒ Object
Add or remove new parameters to the permitted list of an action.
Arguments
action - A Symbol with the action that the controller is performing, like sign_up, sign_in, etc.
keys: - An Array of keys that also should be permitted.
except: - An Array of keys that shouldn't be permitted.
block - A block that should be used to permit the action parameters instead of the Array based approach. The block will be called with an ActionController::Parameters instance.
Examples
# Adding new parameters to be permitted in the `sign_up` action.
devise_parameter_sanitizer.permit(:sign_up, keys: [:subscribe_newsletter])
# Removing the `password` parameter from the `account_update` action.
devise_parameter_sanitizer.permit(:account_update, except: [:password])
# Using the block form to completely override how we permit the
# parameters for the `sign_up` action.
devise_parameter_sanitizer.permit(:sign_up) do |user|
user.permit(:email, :password, :password_confirmation)
end
Returns nothing.
Also I quote
If you have multiple Devise models, you may want to set up a different parameter sanitizer per model. In this case, we recommend inheriting from Devise::ParameterSanitizer and adding your own logic:
class ApplicationController < ActionController::Base
protected
def devise_parameter_sanitizer
if resource_class == User
User::ParameterSanitizer.new(User, :user, params)
else
super # Use the default one
end
end
end
User::ParameterSanitizer.new(User, :user, params) will call this initializer method from parameter_sanitizer.rb source code
def initialize(resource_class, resource_name, params)
#auth_keys = extract_auth_keys(resource_class)
#params = params
#resource_name = resource_name
#permitted = {}
DEFAULT_PERMITTED_ATTRIBUTES.each_pair do |action, keys|
permit(action, keys: keys)
end
end
so basically you are calling initialize(User, :user, params), I don't understand why devise is accepting params in this method, as it has his own way of allowing attributes by saving a static hash of permitted field.
DEFAULT_PERMITTED_ATTRIBUTES = {
sign_in: [:password, :remember_me],
sign_up: [:password, :password_confirmation],
account_update: [:password, :password_confirmation, :current_password]
}
and the permitting them with a loop
DEFAULT_PERMITTED_ATTRIBUTES.each_pair do |action, keys|
permit(action, keys: keys)
end
In this initialize method you save the params as an instance variables #params so in your method you should do:
class Employer::ParameterSanitizer < Devise::ParameterSanitizer
def initialize(*)
super
#params.permit(:sign_up, keys: [:forename, :surname, :username])
end

User birth date params not saving

I have a small rails app, but i'm having trouble getting some information that i'm trying to implement into the user to save. My app as of right now asks for a username and password for signing up. I did this by using the devise gem. However I want to also add an age check to the app, and this is where i've been running into problems.
My DB column is set at (in my schema)
t.date "birth_date"
My view is at
<%= f.input :birth_date, required: true, start_year:1900 %>
My controller has two parts to it:
def create
#user = current_user.build(user_params)
end
private
def user_params
params.require(:user).permit(:birth_date)
end
Whenever i try to log in and create a birth_date for my new user, in the console when I check, the birth_date is still set at nil. Would anyone know what i am missing with this? (I think i'm getting tripped up with Devise handling some things already)
Assuming you are trying to do input birth_date of the user as a part of sign_up process and using devise for this purpose you need to whitelist birth_date params explicitly.
Best way of doing that is using your own registerations_controller and inheriting it from devise
class Users::RegistrationsController < Devise::RegistrationsController
before_action :configure_sign_up_params, only: :create
before_action :configure_account_update_params, only: :update
protected
# If you have extra params to permit, append them to the sanitizer.
def configure_sign_up_params
devise_parameter_sanitizer.permit(:sign_up, keys: [:birth_date])
end
# If you have extra params to permit, append them to the sanitizer.
def configure_account_update_params
devise_parameter_sanitizer.permit(:account_update, keys: [:bith_date])
end
end
#in routes.rb
devise_for :users, controllers: {registrations: "users/registrations"}
since you using devise, and additional field while register, I think you should overwrite devise, here is link for reference, create registration controller as follow
app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
def create
super do
resource.birth_date = params[:birth_date]
resource.save
end
end
end
make sure you also have devise routes
app/config/routes.rb
devise_for :users, :controllers => {:registrations => "registrations"}
Assuming this your UsersController, separate from Devise controllers, you just need to save it to db:
def create
#user = current_user.update(user_params)
end
But you might need to change the birthday in params (which is a string) to a date object first, depending on your column type.
Also you might consider moving this to #update as this is really more an #update action than #create.

Custom field for devise on Rails 5

I have installed devise gem and added custom fields to database for fullname and location as strings.
I updated edit and new form pages as:
<%= f.input :fullname, required: true %>
<%= f.input :location %>
But it doesn't save or update this fields.
I can't see any controller for that
What am I missing? I went through tens of tutorials, but can't figure it out.
I'm using Rails 5.1.3 and Ruby 2.4.0p0.
You can do it in the "lazy way" by using the configure_permitted_parameters before filter.
In your ApplicationController add the protected method specifying the keys to permit in the devise_parameter_sanitizer. Then add a before_action callback pointing to this method if the controller being used is a devise registered controller.
In your case maybe something like:
class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
permit_attrs(%i[fullname location])
end
def permit_attrs(attrs)
%i[sign_up account_update].each do |action|
devise_parameter_sanitizer.permit(action, keys: attrs)
end
end
end

Rails 4- Devise & User routes Clashing?

I set up Devise for authentication on a rails 4 app. I tested sign up, sign in and edit forms. Everything worked fine.
Then I needed a form to get additional inputs from users. So I created new user routes to allow me to update/edit user records. Now my devise edit user form doesn't do anything when I click on submit.
I'm guessing this is because of some clash with the new routes but I could be wrong. Should I check something else?
my routes:
devise_for :users
resources :users, only: [:update, :edit]
demo app at http://mktdemo.herokuapp.com/users/edit - Sign in as test#test.com pwd: test1234.
application controller:
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) << :name
devise_parameter_sanitizer.for(:account_update) << :name
end
end

Configuring permit for 2 user models in Devise

I've been busting myself for a ton of hours now on how to do this.
I have 2 models.
intern.rb
company.rb
I've been able to add custom fields on registration, for me that was :name. I did that by adding:
before_filter :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |i| i.permit(:email, :password, :name) }
end
I've been reading up on the devise readme and trying to understand how to add it so it's specific to one user model. But I get an error every single time.
I tried creating a controller called:
interns_controller.rb
with the code:
class Intern::ParameterSanitizer < Devise::ParameterSanitizer
def sign_up
default_params.permit(:email, :password, :name)
end
end
and then adding this into the
application_controller.rb
code:
protected
def devise_parameter_sanitizer
if resource_class == Intern
Intern::ParameterSanitizer.new(Intern, :intern, params)
else
super
end
end
however I get an error. What am I doing wrong here?
Image with error: http://s12.postimg.org/fqpwyzzdp/Screen_Shot_2014_06_17_at_15_41_58.png

Resources