How to have strong parameters on devise 'edit' view? - ruby-on-rails

I followed these instructions and now have time_zone as a field when the user signs up.
However, the user cannot edit that field, when I try:
Unpermitted parameter: :time_zone
What I know
Since the approach works on /sign_up, I suspect something has to be done to the before_action to allow the time_zone parameter to work on other pages. e.g. editing / adding to this:
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:time_zone])
end
That's my best guess, and I'm not sure how to do it if it is correct.
Also, I'm not sure if :sign_up is referring to a route, a controller method or something else?
Note
Devise docs on strong parameters
What I've tried
Attempt 1
def configure_permitted_parameters
devise_parameter_sanitizer.permit([:sign_up, :update], keys: [:time_zone])
end
2
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:time_zone])
devise_parameter_sanitizer.permit(:update, keys: [:time_zone])
end
3
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:time_zone])
devise_parameter_sanitizer.permit(:edit, keys: [:time_zone])
end

Got it!
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:time_zone])
devise_parameter_sanitizer.permit(:account_update, keys: [:time_zone])
end
That and devise's other methods can be found here: https://github.com/heartcombo/devise#strong-parameters

Related

NoMethodError in Devise::RegistrationsController#create Undefined method user_url

I created user table using devise and then added two more columns in it. Then also added the before_action in the Application Controller:
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:name,:email,:password,:usertype])
devise_parameter_sanitizer.permit(:account_update, keys: [:name,:email,:password,:current_password,:usertype])
end
Now the issue is when I sign up it gives me an error. Transaction is committed but I guess the devise doesnt knows the url or something like that
The error I get is like this:
undefined method `user_url' for #<Devise::RegistrationsController:0x0000000000e100>
if options.empty?
recipient.public_send(method, *args)
else
recipient.public_send(method, *args, options)
end

is it necessary or good practice to sanitize the parameters for all three devise actions?

The Devise docs state that there are three actions that allow parameters to be passed on down to the model: :sign_up, :sign_in, and :account_update. The following example (based off their doc) suggests that I use a before filter.
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:email, :username, :website, :invitation_code])
end
They don't explicitly state that it's a good idea to also sanitize parameters for the other two actions, or if it's a good idea to sanitize other (non-Devise) model params. This is where I'm confused. Should I add to the above code so that it's like this?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:email, :username, :website, :invitation_code])
devise_parameter_sanitizer.permit(:sign_in, keys: [:email, :username, :password])
devise_parameter_sanitizer.permit(:account_update, keys: [:email, :firstname, :lastname, :password, :password_confirmation, :website])
end
Also, how do I know that the parameters are being converted to a hash?
You don't need to sanitize parameters that are never used. Presumably in your login (:sign_in in devise) you're only using username and password so there is no need to sanitize any extra parameters there.
If the user can update his/her first_name, website and so on in your edit form you're gonna need that however for the :account_update parameters.

Rails 5, Undefined method `for' for #<Devise on line devise_parameter_sanitizer.for

I am working with Rails 5
I aded new field username in model User.
class Users::RegistrationsController < Devise::RegistrationsController
before_action :configure_permitted_parameters
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up).push(:username)
end
end
During registration is displayed error: undefined method `for' for # Did you mean? fork
Trace:
NoMethodError (undefined method `for' for #
Did you mean? fork):
app/controllers/users/registrations_controller.rb:7:in `configure_permitted_parameters'
Rendering /usr/local/rvm/gems/ruby-2.3.0/gems/actionpack-5.0.0.rc1/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout
Rendering /usr/local/rvm/gems/ruby-2.3.0/gems/actionpack-5.0.0.rc1/lib/action_dispatch/middleware/templates/rescues/_source.html.erb
Rendered /usr/local/rvm/gems/ruby-2.3.0/gems/actionpack-5.0.0.rc1/lib/action_dispatch/middleware/templates/rescues/_source.html.erb (5.0ms)
Rendering /usr/local/rvm/gems/ruby-2.3.0/gems/actionpack-5.0.0.rc1/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb
Rendered /usr/local/rvm/gems/ruby-2.3.0/gems/actionpack-5.0.0.rc1/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (2.9ms)
Rendering /usr/local/rvm/gems/ruby-2.3.0/gems/actionpack-5.0.0.rc1/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb
Rendered /usr/local/rvm/gems/ruby-2.3.0/gems/actionpack-5.0.0.rc1/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (1.2ms)
Rendered /usr/local/rvm/gems/ruby-2.3.0/gems/actionpack-5.0.0.rc1/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout (118.1ms)
Who can help? How solve this problem?
According to the documentation:
The Parameter Sanitaizer API has changed for Devise 4
class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:username])
end
end
If you just change the .for to .permit it works as well. For example:
devise_parameter_sanitizer.permit(:sign_up) { |u| u.permit({ roles: [] }, :email, :password, :password_confirmation, :username) }
It works in both Rails 4.2.x and Rails 5.0.x
Don't forget devise_parameter_sanitizer.permit(:account_update, keys: [:username])
I think you missed account_update in your controller's configure_permitted_parameters method, you need to follow the devise pattern. Devise has a an account update page. You can find this in views/devise/registrations/edit.html.erb, and your code is also not going to work in the sign_up page, here you specified sign_up page
To update your user table, the minute you submit an update in your users/edit, or if you are submitting a username in the sign_up page you need to follow this devise pattern, to update the database User table. Even if you added a new column to the user table, you would have to add it to the configure_permitted_parameters method. In your case it's username, but you missed account_update as well. You're basically saying that you want to update the username or add the string to username field without following the Devise pattern. Any field you add to the User table should follow this Devise pattern. Also you can specify which page is permitted to update this username. In my example below, i'm using the devise update page. So like I said, even if you added a custom field name to Users table you need to follow this pattern. If you have another page where you need to add username, you would just do the same thing.
class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:username])
devise_parameter_sanitizer.permit(:account_update, keys: [:username])
end
end
Next make sure in your user.rb you have validate username in your User model.
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
validates :username, presence: true
end
To update your user table, the minute you submit an update in your users/edit, or if you are submitting a username in the sign_up page you need to follow this devise pattern, to update the database User table. Even if you added a new column to the user table, you would have to add it to the configure_permitted_parameters method. In your case it's username, but you missed account_update as well. You're basically saying that you want to update the username or add the string to username field without following the Devise pattern. Any field you add to the User table should follow this Devise pattern. Also you can specify which page is permitted to update this username. In my example below, i'm using the devise update page. So like I said, even if you added
class ApplicationController < ActionController::Base
before_action :configure_permitted_paramters, if: :devise_controller?
protected
def configure_permitted_paramters
devise_parameter_sanitizer.permit(:sign_up, keys: [:fullname])
devise_parameter_sanitizer.permit(:account_update, keys: [:fullname,
:phone_number, :description, :email, :password])
end
end

How devise methods are available in ApplicationController.rb?

Is ApplicationController inherits from DeviseController?
Otherwise how devise methods are available in ApplicationController.
ApplicationController inherits from ActionController::Base, which
defines a number of helpful methods.
ref
Devise::Controller has a several modules that's hooked up in to ActionController on_load.
For example the Devise::Controller::Helpers module defines and loads helpers below:
# Generated methods:
# authenticate_user! # Signs user in or redirect
# authenticate_admin! # Signs admin in or redirect
# user_signed_in? # Checks whether there is a user signed in or not
# admin_signed_in? # Checks whether there is an admin signed in or not
# current_user # Current signed in user
# current_admin # Current signed in admin
# user_session # Session data available only to the user scope
# admin_session # Session data available only to the admin scope
#
# Use:
# before_action :authenticate_user! # Tell devise to use :user map
# before_action :authenticate_admin! # Tell devise to use :admin map
ApplicationController doesn't inherit from DeviceController. ApplicationController inherits from ActionController::Base. In ApplicationController the method you talking about configure_permitted_parameters is used with before_filter which is callback.
before_filter :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:username, :email, :password) }
devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:username, :password, :remember_me) }
end
No , Application Controller doesn't inherits from Devise controller.It is the base.To use devise methods in it, you can use the below:
before_filter :configure_permitted_parameters, if: :devise_controller?
def configure_permitted_parameters
devise_parameter_sanitizer.for(:account_update) << [:first_name, :last_name, :is_active]
devise_parameter_sanitizer.for(:sign_in) << [:user_name]
devise_parameter_sanitizer.for(:sign_up) << [:first_name, :last_name,:username,:is_active]
end
def after_sign_in_path_for(resource)
"some path"
end
No, ApplicationController is the base, like the name, is the controller for the all application.
ApplicationController is extended from DeviseController.

Adding Username to devise rails 4

I have a rails 4 application using devise. I'm trying to allow users to have a username associated with them.
I've added a username (string) column to the Users table, and had my Application controller look like this:
class ApplicationController < ActionController::Base
before_filter :configure_permitted_parameters, if: :devise_controller?
protect_from_forgery with: :exception
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:username, :email) }
end
end
and I've also added a field for the username on the users/sign_up page.
But I get this error:
undefined local variable or method `devise_parameter_sanitizer' for #<Devise::RegistrationsController:0x00000101378a28>
So basically my question is why is this error appearing, or how else can I get a user to get a username?
Thanks for all help!
You're only permitting the username to be allowed on the sign in method, but I'm assuming when you create a new user, it's on the sign up method. So try this:
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:username, :email, :password, :password_confirmation) }
end
Source: https://github.com/plataformatec/devise#strong-parameters

Resources