Ruby on rails devise is not permitting all fields - ruby-on-rails

In ruby on rails i use devise for authentication and add the first and last name fields to the database. The new view looks like
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div class="field">
<%= f.label :first_name %><br />
<%= f.text_field :first_name, autofocus: true %>
</div>
<div class="field">
<%= f.label :last_name %><br />
<%= f.text_field :last_name, autofocus: true %>
</div>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true %>
</div>
<div class="field">
<%= f.label :password %>
<% if #minimum_password_length %>
<em>(<%= #minimum_password_length %> characters minimum)</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "off" %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "off" %>
</div>
<div class="actions">
<%= f.submit "Sign up" %>
</div>
<% end %>
The controller looks like this
private
def sign_up_params
params.require(:user).permit(:email, :password, :password_confirmation,:first_name, :last_name)
end
def account_update_params
params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation, :current_password)
end
When creating the account I get a successful request but I am when I look at the database only the first name attribute show up and not the last name attribute. Form the sql queries generated only the first name attribute gets inserted into the sql statement.

Check Following Code, it will help you
class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up) do |user_params|
user_params.permit({ roles: [] }, :email, :password, :password_confirmation)
end
end
end
And for extra help read Devise Strong Parameters topic.

There are a few things you could try:
First do a bang class permitting all variables to be entered in the form and see if last_name gets saved. by declaring .permit! and removing (:email, :password, :password_confirmation, etc...)
If last_name gets saved when banging that class - You should see if entering the correct classes in the form_for tag helps you.
<%= form_for(user, as: user, url: registration_path(user)) do |f| %>
If not, look in your db/schema file and see if you accidently migrated last_name as something other than a string.

Related

How to show validation errors for a login form when fields are empty on submit

I'm using the Devise gem for authentication and for the login form when I click on "Log in" with the fields blank I get the error "Invalid Email or password". I think it would be nice just like the registration form to have errors like "Name can't be blank" or "Email can't be blank" depending on the field that is blank. How can one achieve that?
Log in view
<h2>Log in</h2>
<%= form_for(resource, as: resource_name, url: session_path(resource_name), data: { turbo: false }) do |f| %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
</div>
<div class="field">
<%= f.label :password %><br />
<%= f.password_field :password, autocomplete: "current-password" %>
</div>
<% if devise_mapping.rememberable? %>
<div class="field remember">
<%= f.check_box :remember_me %>
<%= f.label :remember_me %>
</div>
<% end %>
<div class="actions">
<%= f.submit "Log in" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_action :authenticate_user!
before_action :update_allowed_parameters, if: :devise_controller?
def after_sign_up_path_for(_resource)
groups_path
end
def after_sign_in_path_for(_resource)
groups_path
end
protected
def update_allowed_parameters
devise_parameter_sanitizer.permit(:sign_up) do |u|
u.permit(:name, :email, :password, :password_confirmation)
end
devise_parameter_sanitizer.permit(:account_update) do |u|
u.permit(:name, :email, :password, :password_confirmation, :current_password)
end
end
end
Its pretty trivial to just add a client side validation which will provide immediate feedback if you want to:
# app/views/devise/sessions/new.html.erb
<h2>Log in</h2>
<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email", required: true %>
</div>
<div class="field">
<%= f.label :password %><br />
<%= f.password_field :password, autocomplete: "current-password", required: true %>
</div>
<% if devise_mapping.rememberable? %>
<div class="field">
<%= f.check_box :remember_me %>
<%= f.label :remember_me %>
</div>
<% end %>
<div class="actions">
<%= f.submit "Log in" %>
</div>
<% end %>
<%= render "devise/shared/links" %>`
The views in your application will take priority over those defined by the engine.
The reason why Devise doesn't actually use model validation at all for sessions is that models are not context aware and adding this feature would add a lot of complexity for very little gain.
Your model doesn't have a concept of "signing in" so if you called resource.valid? it will fire all the validations for creating a record like for example uniqueness of the email.
While you could do this by creating a form object or by overriding the controller method and adding the errors "inline" it provides very little additional value in safeguarding your application against bad user input which is what server side validations are primarily intendended to do (user feedback is the secondary purpose). YAGNI.

How to set the user creation through devise gem to be by default developer

I am working on a rails application (ruby 3 and rails 7). I have two models. One is User(which comes by devise gem) and the other one is Role. User belongs to role and role has many users. What I am trying to do is when a new user is signing up, he/she should be by default developer.
The one way through which I solved this is by writing default value in the migration file of users but that approach is prohibited by my supervisor. Is there any other way. I dont want to use rolify or any other gems for roles and I have separate table for roles.
Roles: Admin, Developer
I did it. I create some fields when name, bio... When using gem devise
Gem devise https://www.rubydoc.info/github/plataformatec/devise/Devise/ParameterSanitizer
In devise/registrations/new.html.erb
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
// Hidden role_id. EX: role_id is 1 as Developer
<%= f.hidden_field :role_id, autofocus: true, value: "1", autocomplete: "name" %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
</div>
<div class="field">
<%= f.label :password %>
<% if #minimum_password_length %>
<em>(<%= #minimum_password_length %> characters minimum)</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "new-password" %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
</div>
<div class="actions">
<%= f.submit "Sign up" %>
</div>
<% end %>
class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller?
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:role_id])
devise_parameter_sanitizer.permit(:account_update, keys: [:website, :bio])
end
end

Ruby On Rails Devise Register and Login with Username instead of Email

I'm trying add a username field to my register using devise
views/devise/registrations/new/html.erb
<h2>Sign up</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
</div>
<div class="field">
<%= f.label :username %><br />
<%= f.text_field :username, autofocus: true, autocomplete: "email" %>
</div>
<div class="field">
<%= f.label :password %>
<% if #minimum_password_length %>
<em>(<%= #minimum_password_length %> characters minimum)</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "new-password" %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
</div>
<div class="actions">
<%= f.submit "Sign up" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
I got an error: "undefined method `username' for #Usermanagement:0x00007f3db801a8e0"
What did I do wrong? I'm new with ROR so please help me to figure out. Thank you!
in addition to the comment from #hazg, you might find the below link from the devise wiki helpful.
This is a walkthrough on how to add the username to your devise model:
https://github.com/heartcombo/devise/wiki/How-To:-Allow-users-to-sign-in-with-something-other-than-their-email-address
Assuming that you have named your Devise Model a User
Add username field to Devise User Model
$ rails generate migration add_username_to_users name:string
Migration file should look like this
class AddUsernameToUsers < ActiveRecord::Migration
def change
add_column :users, :username, :string
end
end
Migrate the Database
$ rails db:migrate
Generate Devise views
$ rails generate devise:views -v registrations
Update sign up & edit profile form
# views/devise/registrations/new.html.erb
# views/devise/registrations/edit.html.erb
<div class="field">
<%= f.label :username %><br />
<%= f.text_field :username, autofocus: true %>
</div>
Override the devise 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_filter :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:username, :email, :password])
devise_parameter_sanitizer.permit(:account_update, keys: [:username, :email, :password, :current_password])
end
end
Add model validations
class User < ApplicationRecord
validates_presence_of :username
# ...
end

Rails 4: Devise not populating users table with correct information

I have a small Rails 4 app that has Devise and Simple Form installed.
My controller is this:
class UserController < ApplicationController
def create
User.create(user_params)
end
private
def user_params
params.require(:user).permit(:first_name, :last_name, :profile_name, :email, :password, :password_confirmation])
end
end
My form for sign up is as follows:
<h2>Sign up</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div class="field">
<%= f.label :first_name %><br />
<%= f.text_field :first_name, autofocus: true %>
</div>
<div class="field">
<%= f.label :last_name %><br />
<%= f.text_field :last_name, autofocus: true %>
</div>
<div class="field">
<%= f.label :profile_name %><br />
<%= f.text_field :profile_name, autofocus: true %>
</div>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true %>
</div>
<div class="field">
<%= f.label :password %>
<% if #validatable %>
<em>(<%= #minimum_password_length %> characters minimum)</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "off" %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "off" %>
</div>
<div class="actions">
<%= f.submit "Sign up" %>
</div>
<% end %>
However, when I look at the data in the table, it's displaying only the email and password fields. The first and last name, as well as the profile name aren't being stored against the record.
Is there something I've missed here that's preventing all of the fields from being saved on creating a new user? Trying to work out what I've missed here!
Try changing your ApplicationController (the fastest way) according to documentation:
class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) << :first_name << :last_name << :profile_name
end
end
Check according part of documentation.
Hope that helps!
PS. 1.
If you want to customise controller, you should:
Generate one (yours looks like you've created on your own).
rails generate devise:controllers [scope]
Customise generated controller:
class Users::SessionsController < Devise::SessionsController
# your customisations here
#
# GET /resource/sign_in
# def new
# super
# end
...
end
Check this part of documentation.
PS. 2.
In your code you have a line like:
params.require(:user).permit(:first_name, :last_name, :profile_name, :email, :password, :password_confirmation])
it should cause syntax error (I'm surprised if it doesn't). you should remove ] in the end of the list:
params.require(:user).permit(:first_name, :last_name, :profile_name, :email, :password, :password_confirmation])

Rails Devise allow Custom Fields in the Signup Form

I have two types of registration on on my website.
User
Host
There are two models related to Registration
users(id, name, is_host, ...)
hosts(company_name, user_id, status, ...)
Every Host is a User by default on the application. When the User signups on the website he has to enter the following fields
Name
Email
Password
Phone Number
When a Host Signups he has to enter the following
Name
Email
Password
Phone Number
Company Name
On submitting the form as a host it should save the data in the User model and also set the is_host flag to 1 which other wise is 0 and then store the company_name in the hosts model.
What i have done?
I have installed devise and generated the migration tables and generated the scoped views.
What i am trying to achieve?
Add custom fields in the signup form, How to set the strong parameter for the User sign up form?
how to have a separate signup form for the same model and act as a registration for HOSTS
views/users/registrations/new.html.erb
<h2>Sign up!!</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div class="field">
<%= f.label :first_name %><br />
<%= f.text_field :first_name, autofocus: true %>
</div>
<div class="field">
<%= f.label :last_name %><br />
<%= f.text_field :last_name %>
</div>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email %>
</div>
<div class="field">
<%= f.label :password %>
<% if #validatable %>
<em>(<%= #minimum_password_length %> characters minimum)</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "off" %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "off" %>
</div>
<div class="actions">
<%= f.submit "Sign up" %>
</div>
<% end %>
<%= render "users/shared/links" %>
Server Error:
Unpermitted parameters: first_name, last_name
Please look this example....
we create the migration – nothing special here
class AddFieldsToUsers < ActiveRecord::Migration
def change
add_column :users, :first_name, :string
add_column :users, :last_name, :string
end
end
app/views/devise/registrations/new.html.slim
h2 Sign up
= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f|
= devise_error_messages!
div
= f.label :first_name
br
= f.text_field :first_name, autofocus: true
div
= f.label :last_name
br
= f.text_field :last_name
div
= f.label :email
br
= f.email_field :email
div
= f.label :password
br
= f.password_field :password
div
= f.label :password_confirmation
br
= f.password_field :password_confirmation
div
= f.submit 'Sign up'
= render 'devise/shared/links'
Customizing the RegistrationsController
def sign_up_params
devise_parameter_sanitizer.sanitize(:sign_up)
end
def account_update_params
devise_parameter_sanitizer.sanitize(:account_update)
end
registrations controller
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
config/routes.rb
devise_for :users, :controllers => { registrations: 'registrations' }

Resources