Rails Devise allow Custom Fields in the Signup Form - ruby-on-rails

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' }

Related

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

Ruby on rails devise is not permitting all fields

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.

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])

Custom user fields using devise

I'm using devise and I want to add the fields first_name and last_name to the sign_up form.
After creating the respective columns, I tried to sign_up with the new form, but the values of the new fields in DB were nil.
After that I created this 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
But I still get nil in the columns first_name and last_name.
Am I missing something?
The form:
<h2>Sign up</h2>
<%= 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 %></div>
<div><%= f.label :last_name %><br />
<%= f.text_field :last_name %></div>
<div><%= f.label :profile_name %><br />
<%= f.text_field :profile_name %></div>
<div><%= f.label :email %><br />
<%= f.email_field :email, autofocus: true %></div>
<div><%= f.label :password %> <% if #validatable %><i>(<%= #minimum_password_length %> characters minimum)</i><% end %><br />
<%= f.password_field :password, autocomplete: "off" %></div>
<div><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "off" %></div>
<div><%= f.submit "Sign up" %></div>
<% end %>
<%= render "devise/shared/links" %>
1 option.
I think adding the following to application_controller.rb would eliminate the issue (instead of overridding the devise's controller):
private
def configure_devise_params
devise_parameter_sanitizer.for(:sign_up) do |u|
u.permit(:first_name, :last_name, :email, :password, :password_confirmation)
end
devise_parameter_sanitizer.for(:account_update) do |u|
u.permit(:first_name, :last_name, :email, :password, :password_confirmation)
end
end
2 option.
Check passing the controllers: { registrations: 'devise/registrations' } block do devise_for :users line in routes.rb
did you add devise_for :users, :controllers => { registrations: 'devise/registrations' } in your routes file ? If not then add it in your routes file. Other things are looks Okay

rails devise: user and account system

I've been trying to add an account to a user for a couple of days now.
I've installed Devise with no problems, but now I wanted to add a Company Name field to my registration form.
Here's my code:
app/models/account.rb
class Account < ActiveRecord::Base
attr_accessible :name
has_many :users
accepts_nested_attributes_for :users
end
app/models/user.rb
class User < ActiveRecord::Base
belongs_to :account
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :confirmable
attr_accessible :first_name, :last_name, :account_attributes, :account, :email, :password, :password_confirmation, :remember_me
end
app/views/devise/registrations/new.html.erb
<%= 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 %></div>
<div><%= f.label :last_name %><br />
<%= f.text_field :last_name %></div>
<%= f.fields_for :account do |account_form| %>
<div><%= account_form.label :name %><br />
<%= account_form.text_field :name %></div>
<% end %>
<div><%= f.label :email %><br />
<%= f.email_field :email %></div>
<div><%= f.label :password %><br />
<%= f.password_field :password %></div>
<div><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %></div>
<div><%= f.submit "Sign up" %></div>
<% end %>
This is all the code I have. I haven't changed anything more.
And this is the error I got:
Account(#2175324980) expected, got ActiveSupport::HashWithIndifferentAccess(#2169631580)
Thanks in advance.
EDIT
I've found the solution:
I've changed
<%= f.fields_for :account do |account_form| %>
To
<%= f.fields_for :account_attributes, resource.account do |account_form| %>
Now I'm trying to add a :plan to account_form and I'm getting:
Can't mass-assign protected attributes: plan
EDIT 2
Ok, rookie mistake. I've just added :plan to account model.
After that I was getting an query error, I just changed some fields in my DB from null => false to null => true and voila.
I would expect it to look something like this. This involves subclassing devise's registrations controller
#models
class Account < ActiveRecord::Base
attr_accessible :name
has_many :users
end
class User < ActiveRecord::Base
belongs_to :account
accepts_nested_attributes_for :account
attr_accessible :first_name, :last_name, :account_attributes, :account, :email, :password, :password_confirmation, :remember_me
end
#app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
def new
#account = Account.new
super
end
end
#routes
devise_for :users, :controllers => {:registrations => "registrations"}
#view
<%= 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 %></div>
<div><%= f.label :last_name %><br />
<%= f.text_field :last_name %></div>
<%= f.fields_for #account do |account_form| %>
<div><%= account_form.label :name %><br />
<%= account_form.text_field :name %></div>
<% end %>
<div><%= f.label :email %><br />
<%= f.email_field :email %></div>
<div><%= f.label :password %><br />
<%= f.password_field :password %></div>
<div><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %></div>
<div><%= f.submit "Sign up" %></div>
<% end %>

Resources