Devise signup with association - devise

I am working on a project app with patients and doctors. During sign up the patient with choose their doctor from a drop down list. I am not having any luck in associating the doctor and patient. I'm not sure if it has to to with devise or what but any help would be greatly appreciated. Below is a copy of the Patients Registrations controller and the signup.
class Patients::RegistrationsController < Devise::RegistrationsController
before_action :configure_sign_up_params, only: [:create]
# before_action :configure_account_update_params, only: [:update]
# GET /resource/sign_up
# def new
# super
# end
# POST /resource
# def create
# super
# end
# GET /resource/edit
# def edit
# super
# end
# PUT /resource
# def update
# super
# end
# DELETE /resource
# def destroy
# super
# end
# GET /resource/cancel
# Forces the session data which is usually expired after sign
# in to be expired now. This is useful if the user wants to
# cancel oauth signing in/up in the middle of the process,
# removing all OAuth session data.
# def cancel
# super
# end
# protected
# If you have extra params to permit, append them to the sanitizer.
def configure_sign_up_params
devise_parameter_sanitizer.permit(:sign_up, keys: [:first_name, :last_name, doctor_ids: []])
end
# The path used after sign up.
def after_sign_up_path_for(resource)
patient_path(resource)
end
end
<h2>Sign up</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { data: { turbo: false} } ) do |f| %>
<%= render "patients/shared/error_messages", resource: resource %>
<div class="field">
<%= f.label :first_name %><br />
<%= f.text_field :first_name, autofocus: true, autocomplete: "email" %>
</div>
<div class="field">
<%= f.label :last_name %><br />
<%= f.text_field :last_name, autofocus: true, autocomplete: "email" %>
</div>
<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>
<%= collection_select(resource, :doctor_id, Doctor.all, :id, :fullname, :prompt => 'Select your Doctor') %>
<div class="actions">
<%= f.submit "Sign up" %>
</div>
<% end %>
<%= render "patients/shared/links" %>

Related

Devise nested form not creating profile

Rails 5.0.1
Devise 4.2.0
Hello, I'm building an app in which the user must fill a form to sign up, which includes the registration info for devise, and some personal info por their profile. I have made the models for user and profile, established their one to one relation, and added accept_nested_attributes_for :profile inside the user. I have also modified the registrations views to include f.fields_for for the profile, and until that point everything seems to work fine.
But, when I try to create a new user, and fill the required information, I get an error inside the view (from devise I guess) saying:
1 error prohibited this user from being saved
Profile user must exist
I have already followed many guides on how to create a nested form with devise, and none of them seem to have this issue, and I have also searched a lot with no answer. Here are some snippets from my registration controller, user and profile model, and registrations/new view:
registrations_controller
class Users::RegistrationsController < Devise::RegistrationsController
before_action :configure_sign_up_params, only: [:create]
before_action :configure_account_update_params, only: [:update]
def new
build_resources({})
resource.build_profile
respond_with self.resource
end
protected
def configure_sign_up_params
devise_parameter_sanitizer.permit(:sign_up,
keys: [:email, :password,
:password_confirmation,
profile_attributes: [:name, :art_name,
:birth_date, :location]])
end
User model
class User < ApplicationRecord
has_one :profile, dependent: :destroy
before_create :build_profile
accepts_nested_attributes_for :profile
# Devise configuration.....
end
Profile model
class Profile < ApplicationRecord
belongs_to :user
end
Registrations/new view
<h2>Nueva Cuenta</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<%= f.fields_for :profile do |b| %>
<div class="field">
<%= b.label :name, "Nombre" %><br />
<%= b.text_field :name %>
</div>
<div class="field">
<%= b.label :art_name, "Nombre artistico" %><br />
<%= b.text_field :art_name %>
</div>
<div class="field">
<%= b.label :birth_date, "Fecha de nacimiento" %><br />
<%= b.date_field :birth_date %>
</div>
<div class="field">
<%= b.label :location, "Ubicacion" %><br />
<%= b.text_field :location %>
</div>
<% end %>
<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 %>
<%= render "devise/shared/links" %>
My guess is that it has something to do with the sanitizers, I'm not completely sure how do I pass each attribute through, since most of the guides that explained this did with an older version of devise.
Thanks for your attention.
in your profile model, try this:
belongs_to :user, optional: true
it works for me

Getting attributes in nested model rails 3.2

I have two models user and profile.
I want to save the username and password in user and other user profile details in
profile.
Now,
The user model has:
has_one :profile
accepts_nested_attributes_for :profile
attr_accessible :email, :password,:profile_attributes
The profile model has
belongs_to :user
attr_accessible :firstname, :lastname
The user controller has
def new
#user = User.new
#profileattr = #user.build_profile
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to root_url, :notice => "user created successfully!"
else
render "new"
end
end
The view new.html.erb have fields for both user and profile.
view has:
<%= form_for #user do |f| %>
<% if #user.errors.any? %>
<div class="error_messages">
<h2>Form is invalid</h2>
<ul>
<% for message in #user.errors.full_messages %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<%= f.label :email %><br />
<%= f.text_field :email %>
</p>
<p>
<%= f.label :password %><br />
<%= f.password_field :password %>
</p>
<%= f.fields_for #profileattr do |pf|%>
<p>
<%= pf.label :firstname %><br />
<%= pf.text_field :firstname %>
</p>
<p>
<%= pf.label :lastname %><br />
<%= pf.text_field :lastname %>
</p>
<% end %>
<p class="button"><%= f.submit %></p>
<% end %>
However,when I run this web application it shows error:
Can't mass-assign protected attributes: profile
on debug I found the user has attributes as:
:email:abc#gmail.com
:password:secret
:profile
---:firstname:abc
---:lastname:xyz
so,instead of expected params[:profile_attributes] the view returning params[:profile]
leading to mass-assignment error.so what is going wrong?
Did you try
<%= f.fields_for :profile do |pf|%>
?

How to flash error for particular validation

I am trying to flash messages in a form when they do not meet the validation requirements but can't work out how to achieve this.
I have the following setup:
models/item.rb
class Item < ActiveRecord::Base
attr_accessible :condition, :day, :description, :subtitle, :title
validates :user_id, presence: true
validates :title, presence: true
validates :description, presence: true, length: { minimum: 20 }
belongs_to :user
end
controllers/items_controller.rb
class ItemsController < ApplicationController
before_filter :authenticate_user!
def new
#item = Item.new
end
def show
#item = Item.find(params[:id])
end
def create
#item = current_user.items.build(params[:item])
if #item.save
flash[:success] = "Your item has been saved"
redirect_to root_path
else
render 'new'
end
end
def destroy
#item.destroy
redirect_back_or root_path
end
end
and finally views/items/new.html.erb
<h1>Items Base</h1>
<div class="row">
<div class="span6 offset3">
<%= form_for(#item) do |f| %>
<%= f.label :title, "Title" %>
<%= f.text_field :title %>
<%= f.label :subtitle, "Subtitle" %>
<%= f.text_field :subtitle %>
<%= f.label :condition, "Condition" %>
<%= f.number_field :condition %>
<%= f.label :description, "Description" %>
<%= f.text_field :description %>
<%= f.label :day, "Day" %>
<%= f.text_field :day %>
<%= f.submit "List", class: "btn btn-large btn-primary" %>
<% end %>
</div>
</div>
Essentially I would like to be able to flash the message "Description too short!" when the user leaves it blank or below 20 characters, or flash the message "Title required" if it is left blank. Any thoughts on how best to achieve this. Also if anyone has any good resources on working with the flash it would be much appreciated. Thanks.
Here is how I do it:
Here is the form:
<%= form_for(#client) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :company_name %>
<%= f.text_field :company_name %>
<%= f.submit "Save changes", class: "btn btn-large btn-primary" %>
<% end %>
And here is my error_messages partial:
<% if object.errors.any? %>
<div id="error_explanation">
<div class="alert alert-error">
The form contains <%= pluralize(object.errors.count, "error") %>.
</div>
<ul>
<% object.errors.full_messages.each do |msg| %>
<li>* <%= msg %></li>
<% end %>
</ul>
</div>
<% end %>

Unsure about how to use rails 3 check_box

I have a User form as follows, with a checkbox to set the user as admin:
<%= form_for #user do |f| %>
<%= render 'shared/error_messages', :object => f.object %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :email %><br />
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :password %><br />
<%= f.password_field :password %>
</div>
<div class="field">
<%= f.label :password_confirmation, "Confirmation" %><br />
<%= f.password_field :password_confirmation %>
</div>
<%= hidden_field_tag :group_id, #group.id %>
**<div class="field">
<%= f.check_box :admin %>
</div>**
<div class="actions">
<%= f.submit "Sign up" %>
</div>
<% end %>
My Users table is as follows
create_table "users", :force => true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
t.string "email"
t.string "encrypted_password"
t.string "salt"
t.boolean "admin", :default => false
t.integer "group_id"
end
And my User create action is as follows in my Users Controller
def create
#group = Group.find(params[:group_id])
#user = #group.users.build(params[:user])
if #user.save
flash[:success] = "You have created a new user"
redirect_to groups_path
else
#title = "Sign up"
render 'new'
end
end
But when I test user.admin for true, it doesn't show as true
<% #users.each do |user| %>
<li>
<%if user.admin == true %>
<%= link_to user.name, user %>
<% end%>
</li>
<% end %>
The form works fine otherwise, only the check_box doesn't set the user.admin to true. Have I missed a key step somewhere? thanks
Are you sure the value is getting set to true in the database? Check it out using dbconsole:
rails dbsconsole
If not, then you may need to make sure it's accessible in your User model:
attr_accessible :admin
Also, as a side note boolean values come with a bonus question mark method in ActiveRecord, so you could do this instead:
if user.admin?

rails - confused about routing and params

I have a two models, Group and User
User belongs_to Group and
Group has_many Users
In my groups/show.html.erb I have the user sign-up form
<h1>Create user</h1>
<%= form_for #user do |f| %>
<%= render 'shared/error_messages', :object => f.object %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :email %><br />
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :password %><br />
<%= f.password_field :password %>
</div>
<div class="field">
<%= f.label :password_confirmation, "Confirmation" %><br />
<%= f.password_field :password_confirmation %>
</div>
<div class="actions">
<%= f.submit "Sign up" %>
</div>
<% end %>
To get a relation between the Group and the User I have a create method in my Users controller as follows
def create
#group = Group.find(params[:group][:id])
#user = #group.users.build(params[:user])
if #user.save
flash[:success] = "You have created a new user"
redirect_to group_path
else
#title = "Create user"
render 'new'
end
end
I have also tried:
#group = Group.find(params[:id])
and
#group = Group.find(params[:group_id])
But I still get an error
Essentially I want to create new users in the group/show.html.erb and associate that user with the group where the user was created. If the user is created in groups/3 for example, how do I set my create method in the Users controller to make sure this relation holds?
In general I've been following the Hartl Rails tutorial book at http://ruby.railstutorial.org/chapters/user-microposts#sec:creating_microposts and following the approach for forms and create methods. However I am not sure how to get the params for groups/3 into the find method like #group = Group.find(?????)
Can someone please enlighten me, this issue has been bothering me for a few days now.
Thanks in advance
After the form is submitted, it takes you to the users#create. This route doesn't have a group_id segment.
To pass group_id there, you need to store it in a hidden field in your form.