Adding Fields To Devise Sign Up Using Rails 4 - ruby-on-rails

To start off, I'm new to rails, so I'm still getting the hang of things.
I'm attempting to add two fields to the Devise sign up page, a first name field and a last name field. I've gone ahead and changed the view and the controller in order to attempt this. They look like this:
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_devise_permitted_parameters, if: :devise_controller?
protected
def configure_devise_permitted_parameters
registration_params = [:firstName, :lastName, :email, :password, :password_confirmation]
if params[:action] == 'update'
devise_parameter_sanitizer.for(:account_update) {
|u| u.permit(registration_params << :current_password)
}
elsif params[:action] == 'create'
devise_parameter_sanitizer.for(:sign_up) {
|u| u.permit(registration_params)
}
end
end
end
View:
<h2>Sign up</h2>
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div><%= f.label :email %><br />
<%= f.email_field :email, :autofocus => true %></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.label :firstName %><br />
<%= f.fName_field :firstName %></div>
<div><%= f.label :lastName %><br />
<%= f.lName_field :lastName %></div>
<div><%= f.submit "Sign up" %></div>
<% end %>
<%= render "devise/shared/links" %>
However, I get this error when I go to view the page:
undefined method `fName_field' for #<ActionView::Helpers::FormBuilder:0x00000003c89940>
Where must I define those methods? or are they automatically defined somewhere else?
Thanks for any help.

With "f.something" you can just define the type of the field in the form. Try something like
<%= f.text_field :lastName %>
This should work.
You can read about the available types of fields here: http://apidock.com/rails/ActionView/Helpers/FormHelper/form_for

create a migration like this to add first name and last name to users table:-
class AddFirstnameAndLastnameToUsers < ActiveRecord::Migration
def change
add_column :users, :firstName, :string
add_column :users, :lastName, :string
end
end
And add this to your view :-
<div><%= f.label :firstName %><br />
<%= f.text_field :firstName%></div>
<div><%= f.label :lastName %><br />
<%= f.text_field :lastName %></div>
You can not do f. to column of the table, you do it on the type of the field.

undefined method `fName_field'
This means you don't have the fName column in your database
If you have access to your DB, you'll see that Devise produces a table with a bunch of columns inside. By default, these columns only include email & password for the user. To add more, you first need to add the column to the database & then you should be able to do what you're doing with it.
There's a good railscast on devise you can see how to do this

I know it's a very common mistake done by a rookie while creating a registration form on the very first time because the devise puts all of the fields like f.email_field,f.password_field etc but these all are valid controls, so the developer gets confuse to type an attribute with _field
The 'fname_field' you used to define your first name is not acceptable as the form controls.
Please verify all of the controls which can be used here
and as per the current scenario, you should go for f.text_field

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.

Custom sign-up form in Devise not working

I have looked at other answers on here and have yet to find one. I am creating a Rails 4 app that allows users to sign in and create a profile. I am using Devise gem for user authentication.
What I want to do is have the user also type in their name and a description of themselves during the signup process. When submit the form the database will be updated with this info as well. Here is what I have done:
1) I ran a migration to create the new columns, "name" and "description", in the users table
2) I ran rails generate devise:views. This allows me to access devise>views>registrations>new.html.erb where I included the "name" label and field. I just used the other labels and fields as a guide. I now get an error saying name_field method is undefined. Where are the other ones like email_field and password_field defined?
<h2>Sign up</h2>
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div><%= f.label :email %><br />
<%= f.email_field :email, :autofocus => true %></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.label :name %><br />
<%= f.name_field :name %></div>
<div><%= f.submit "Sign up" %></div>
<% end %>
<%= render "devise/shared/links" %>
Any help in getting this working I would greatly appreciate.
There's no method on the Rails form object that says name_field. name_field is not a valid HTML form input type. Did you do find and replace? You should change
<%= f.name_field :name %>
to
<%= f.text_field :name %>
UPDATE
Overriding configure_permitted_parameters in app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_filter :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:name, rest_of_user_attrs) }
# you control which attributes can be updated or used for sign in here
end
end
Here's more information for your perusal https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-sign-in-using-their-username-or-email-address
#user2623706 have you configured devise for strong parameters. That may be the problem.

Devise allowing all attributes by default in Rails 4

I'm currently running the following:
Rails 4.0.2
Devise 3.2.2
From the Devise documentation it states that Strong Parameters will block all but the following attributes by default - email, password, password_confirmation, current_password.
I edited the new.html.erb in my registration Devise Views to contain three additional attributes - first_name, last_name, profile_name as shown below.
<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 %><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 %>
<%= render "devise/shared/links" %>
For some reason a user can still register by inputting information in all the fields, even the new fields that I added. Is there a reason my attributes are all being allowed by default?
I'm new to programming and I'm following my first rails tutorial so I'm sure I'm making a completely obvious mistake but I can't figure it out and haven't been able to find the same problem by searching online.
Thank you
Gemfile
gem "strong_parameters"
config/application.rb
config.active_record.whitelist_attributes = false
aplication_controller
before_filter :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) << :first_name
end
With strong parameters there is no implicit validation on the client side as to whether or not the fields are allowed, but these fields will not actually be saved to the database until you explicitly permit them in your controller. You should be able to verify that the controller is blocking those fields by watching your server console during the create/update action.
The user could enter, but it's not permitted for mass assignment. The following are from Devise README:
In case you want to permit additional parameters (the lazy way™) you can do with a simple before filter in your ApplicationController:
class ApplicationController < ActionController::Base
before_filter :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) << :username
end
end
Read more about this on Devise's README, strong parameter section.

Devise Registration form on any page

I'm trying to allow users to sign up for the site on my home/landing page.
I've duplicated the devise registration form into my landing page 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>
<div><%= f.label :profile_name %><br />
<%= f.text_field :profile_name %></div>
<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 %>
<%= render "devise/shared/links" %>
And I've also added the helper methods in my application_controller.rb so that I properly define the resource-
class ApplicationController < ActionController::Base
protect_from_forgery
def resource_name
:user
end
def resource
#resource ||= User.new
end
def devise_mapping
#devise_mapping ||= Devise.mappings[:user]
end
end
However I'm still getting the error undefined local variable or method resource'for #<#:0x007fa816b4b750>`
What am I missing here to properly render a REGISTRATION form on my home landing page?
You need to declare those controller methods as helper methods to access them from the views:
helper_method :resource, :resource_name, :devise_mapping
Just add that line inside your ApplicationController after the methods are defined.
You'll notice that the link you provided actually mentions to put this code in the application helper, not the controller... You can avoid this helper_method declaration if you do it that way.

Resources