Rails: how to let two user models in devise go through registration - ruby-on-rails

In my app there are two models:
Users
Teachers
Registering Teachers is a problem because my registration controller is set up for user registration only (I think), so I keep getting errors about the params missing "user".
Registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
private
def sign_up_params
params.require(:user).permit(:teacher, :teacher_id, :user_id, :username, :first_name, :last_name, :email, :password, :password_confirmation)
end
def account_update_params
params.require(:user).permit(:teacher, :teacher_id, :user_id, :username, :first_name, :last_name, :email, :password, :password_confirmation, :current_password)
end
end
So my questions are:
Do you know a way to tweak the registrations controller to handle both registrations?
Should I even be doing it like this or ought it be handled differently?
Just in case, here is the registration form that is being used. Thanks for your time.
devise>registrations>new.html.erb
<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<div>
<%= f.input :username, required: true, autofocus: true %>
<%= f.input :email, required: true %>
<% if request.fullpath.include?('user') %>
<%= f.input :teacher_id, required: false %>
<% end %>
<%= f.input :password, required: true, hint: ("#{#minimum_password_length} characters minimum" if #minimum_password_length) %>
<%= f.input :password_confirmation, required: false %>
</div>
<div class="form-actions">
<%= f.button :submit, "Sign up" %>
</div>
<% end %>
<%= render "devise/shared/links" %>

In your config/routes.rb
devise_for :users, controllers: { registrations: "registrations" }
devise_for :teachers, controllers: { registrations: "teacher/registrations" }
Create a controller app/controllers/teacher/registrations_controller.rb
class Teacher::RegistrationsController < Devise::RegistrationsController
private
def sign_up_params
params.require(:teacher).permit(:username, :first_name, :last_name, :email, :password, :password_confirmation)
end
def account_update_params
params.require(:teacher).permit(:username, :first_name, :last_name, :email, :password, :password_confirmation, :current_password)
end
end

Related

Password confirmation in Rails 5

This is my view:
<%=form_for [:admin, #user] do |f|%>
<ul>
<% #user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
<%=f.label :name %>
<%=f.text_field :name %>
<%=f.label :email %>
<%=f.text_field :email %>
<%=f.label :password %>
<%=f.password_field :password %>
<%=f.label :password_confirmation %>
<%=f.password_field :password_confirmation%>
<%=f.submit "Submit" %>
<%end%>
Controller code for adding user:
def create
#user = User.new(user_params)
if #user.save
redirect_to admin_users_path
else
render 'new'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password)
end
These are validations in the model:
validates :name, presence: true
validates :email, presence: true
validates :password, presence: true
validates :password, confirmation: { case_sensitive: true }
But confirmation password doesn't work.
Validation works for all (they are required) form elements, except second password input - password_confirmation which can be different from first password input.
User is added to the database even if second password input is empty, because in the validation rules, there is no rule for that .
What am I doing wrong ?
You need to add password_confirmation to user_params in the controller.
I.e.
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end
Try: validates_confirmation_of :password
Model:
class Person < ActiveRecord::Base
validates_confirmation_of :user_name, :password
validates_confirmation_of :email_address, :message => "should match confirmation"
end
View:
<%= password_field "person", "password" %>
<%= password_field "person", "password_confirmation" %>
You could take a look to the validates_confirmation_of.

Ruby on Rails- gem devise, ArgumentError:wrong number of arguments (given 0, expected 1)

I install devise gem and wanted to add some columns on registration page.
app/controllers/users/registrations_controller.rb
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){|u| u.permit(:company_id, :name, :email, :profile, :prefecture_id, :address, :password, :password_confirmation)}
end
app/views/devise/registrations/new.html.erb
<%= simple_form_for(resource, as: resource_name, url:registration_path(resource_name)) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.label :campany_id %><br>
<%= f.collection_select :campany_id, Campany.all, :id, :name, include_blank: true %>
<%= f.input :name, required: true, autofocus: true %>
<%= f.inneput :email, paceholder:"メールアドレス", required: true, autofocus: true %>
<%= f.input :profile, required: true, autofocus: true %>
*<%= f.label :prefecture_id %><br>
<%= f.collection_select :prefecture_id, JpPrefecture::Prefecture.all, :code, :name %>
<%= f.input :address, required: true, autofocus: true %>
<%= f.input :password, required: true, hint: ("#{#minimum_password_length} characters minimum" if #minimum_password_length) %>
<%= f.input :password_confirmation, required: true %>
</div>
<div class="form-actions">
<%= f.button :submit, "新規登録" %>
</div>
<% end %>
config/routes.rb
devise_for :users, controllers: {
registrations: 'users/registrations'
}
When I filled out the form and submitted. It show " ArgumentError:wrong number of arguments (given 0, expected 1)" this error!
Is there some wrong?
Thank you!
In new.html.erb, for input email your input spelling should be f.input, also you have given campany_id but in controller you have used company_id.
And in controller:
def configure_sign_up_params
devise_parameter_sanitizer.permit(:sign_up){|u| u.permit(:company_id, :name, :email, :profile, :prefecture_id, :address)}
end
You only need to permit parameters which have been added by you. You do not need to permit password or confirm_password.
Also all the parameters permitted or which are there in form need to be in your table.
Hope this helps.

Devise: Add User Details in different table

I have two models User and Person
I want to stick with the default table for the user offered by Devise to include only email and password and add User details in Person
Here is my models
class Person < ApplicationRecord
belongs_to :user
end
User Model
class User < ApplicationRecord
...
has_one :person
...
end
I also override RegistrationController.rb to look like this
class RegistrationsController < Devise::RegistrationsController
def sign_up_params
params.require(:user).permit(:first_name, :email, :password, :password_confirmation)
end
end
and here is the view
<h2>Sign up</h2>
<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= f.error_notification %>
<%= f.fields_for :person do |p| %>
<%= p.text_field :first_name %>
<%= p.text_field :last_name %>
<% end %>
<div class="form-inputs">
<%= f.input :email, required: true, autofocus: true %>
<%= f.input :password, required: true, hint: ("#{#minimum_password_length} characters minimum" if #minimum_password_length) %>
<%= f.input :password_confirmation, required: true %>
</div>
<div class="form-actions">
<%= f.button :submit, "Sign up" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
With the code it didn't work, and it didn't update the people column while registration
How Can I get devise to add details in two models using the only one form offered by devise ?
To add email and password in Users Table
and other details e.g. first_name in People Table
Nested-Models setup for simple_form
Add accepts_nested_attributes_for to User model
class User < ActiveRecord::Base
has_one :person
accepts_nested_attributes_for :person
end
Update permit params in controller:
class RegistrationsController < Devise::RegistrationsController
def sign_up_params
params.require(:user).permit(:email, :password, :password_confirmation,
person_attributes: [:first_name, :last_name])
end
end
Change f.fields_for :person to f.simple_fields_for :person in view.
Check https://github.com/plataformatec/simple_form/wiki/Nested-Models
You need to set strong params inside your controller private method as per below:
def sign_up_params
params.require(:user).permit(:first_name, :email, :password, :password_confirmation, person_attributes: [:person_model_attributes])
end
Inside your User model add below line:
accepts_nested_attributes_for :person

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

how to set foreign key through the controller in rails?

I've got an address form nested into a user form but cant get the foreign key to fill. I've seen people suggest using a hidden field, but that seems to be a bad idea from a security standpoint. How exactly do you set the foreign key using the controller? Right now I'm getting Address user can't be blank error when I try to submit
MVC below
user\new.html.erb
<div>
<%= form_for(#user) do |f| %>
<%= render 'shared/error_messages' %>
<%= f.label :rank %>
<%= f.text_field :rank %>
<%= f.label :firstName, "First Name" %>
<%= f.text_field :firstName %>
<%= f.label :lastName, "Last Name" %>
<%= f.text_field :lastName %>
<%= f.label :middleInitial, "Middle Initial" %>
<%= f.text_field :middleInitial %>
<%= fields_for :address do |a| %>
<%= a.label :address %>
<%= a.text_field :address %>
<%= a.label :city %>
<%= a.text_field :city %>
<%= a.label :state %>
<%= a.text_field :state %>
<%= a.label :zip, "Zip Code" %>
<%= a.text_field :zip %>
<% end %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.label :dateOfBirth, "Date of Birth" %>
<%= f.text_field :dateOfBirth %>
<%= f.label :MOS, "MOS" %>
<%= f.text_field :MOS %>
<%= f.label :ets_pcsDate, "ETS/PCS Date" %>
<%= f.text_field :ets_pcsDate %>
<%= f.label :phoneNum, "Phone Number" %>
<%= f.text_field :phoneNum %>
<%= f.label :password %>
<%= f.text_field :password %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.text_field :password_confirmation %>
<%= f.submit "Sign up" %>
<% end %>
</div>
<h1>Users#new</h1>
<p>Find me in app/views/users/new.html.erb</p>
Models
User
class User < ActiveRecord::Base
attr_accessible :MOS, :dateOfBirth, :ets_pcsDate, :firstName,
:lastName, :middleInitial, :phoneNum, :rank, :email, :password,
:password_confirmation
has_secure_password
has_one :address, dependent: :destroy
accepts_nested_attributes_for :address
before_save { |user| user.email = email.downcase }
before_save :create_remember_token
validates :rank, presence: true
validates :firstName, presence: true, length: { maximum: 15 }
validates :lastName, presence: true, length: { maximum: 20 }
validates :middleInitial, presence: true, length: { maximum: 1 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true,
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
validates :dateOfBirth, presence: true
validates :MOS, presence: true
validates :ets_pcsDate, presence: true
validates :phoneNum, presence: true
validates :password, length: { minimum: 6 }
validates :password_confirmation, presence: true
private
def create_remember_token
self.remember_token = SecureRandom.urlsafe_base64
end
end
Address
class Address < ActiveRecord::Base
attr_accessible :address, :city, :state, :zip
belongs_to :user
validates :address, presence: :true
validates :city, presence: :true
validates :state, presence: :true
validates :zip, presence: true
validates :user_id, presence: true
end
Controller
class UsersController < ApplicationController
before_filter :signed_in_user, only: [:index, :edit, :update, :show, :destory]
before_filter :correct_user, only:[:edit, :update]
before_filter :admin_user, only: :destroy
def new
#user = User.new
#user.address.build
end
def create
#user = User.new(params[:user])
#address = #user.build_address(params[:address])
if #user.save
sign_in #user
flash[:success] = "Welcome to B Troop!"
redirect_to #user
else
render 'new'
end
end
def show
#user = User.find(params[:id])
end
def index
#users = User.paginate(page: params[:page])
end
def edit
end
def update
if #user.update_attributes(params[:user])
flash[:success] = "Profile updated"
sign_in #user
redirect_to #user
else
render 'edit'
end
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "User removed"
redirect_to users_path
end
private
def signed_in_user
unless signed_in?
store_location
redirect_to root_path, notice: "Please sign in."
end
end
def correct_user
#user = User.find(params[:id])
redirect_to(root_path) unless current_user?(#user)
end
def admin_user
redirect_to(root_path) unless current_user.admin?
end
end
Removing the user_id validation did the trick.

Resources