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
Related
I recently followed a tutorial about nested forms by Ryan Bates and did basically the same thing as he did just with other names. I wanted to nest assignments in the order form and I would like to build an assignment for every bun to that order and the user should put a count in the form.
So my controller looks like this
def new
#order = Order.new
#buns = Bun.all
#buns.each do |bun|
#order.assignments.build(:bun_id => bun.id)
end
end
And the _form partial looks like this
<%= form_for(#order) do |f| %>
<div class="field">
<%= f.label :user_id %><br />
<%= f.number_field :user_id %>
</div>
<div id="assignments" class="field">
<% f.fields_for :assignments do |builder| %>
<div id="assignment" class="field">
<%= builder.label :count, "Anzahl" %>
<%= builder.text_field :count %>
<%= builder.object.bun_id %>
<% end %>
</div>
</div>
<div class="field">
<%= f.label :due_to %><br />
<%= f.datetime_select :due_to %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
The Order model has this part
has_many :assignments
has_one :user
accepts_nested_attributes_for :assignments
And the Assignments model this one:
attr_accessible :bun_id, :order_id, :count
belongs_to :bun
belongs_to :order
As i log the assignments out there are all, which should be build, so why weren't the fields rendered?
Thanks for your help!
You are missing an equal sign (=) in your erb :
<%= f.fields_for :assignments do |builder| %>
Hello Im using devise to register users, and I want to create a profile related to a user every time a user signs up, the problem is that when I try to add the full name of the person from the profile model on the registration view for devise's user registration, it does not show up...
This are my models:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me, :profile_attributes
has_one :profile, dependent: :destroy
accepts_nested_attributes_for :profile
# attr_accessible :title, :body
end
This is the profile model
class Profile < ActiveRecord::Base
attr_accessible :email, :name, :phone, :code
belongs_to :user
validates_presence_of :user
end
And this is the devise view modified:
<% provide(:title, 'Sign up' ) %>
<h2>Sign up</h2>
<div class="row">
<div class="span6 offset3">
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= render 'shared/error_messages', object: resource %>
<%= f.fields_for :profile do |profile_form| %>
<%= profile_form.label :full_name %>
<%= profile_form.text_field :name %>
<% end %>
<%= f.label :email %>
<%= f.email_field :email %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation %>
<div class="form-actions">
<%= f.submit "Sign up", class: "btn btn-large btn-primary" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
</div>
</div>
I cant see anything wrong to why the name text field would not appear...
Thank you for your help
Figured it out, it was so simple I feel bad... so here it is:
I forgot to generate a new profile on the form so it ends up looking kind of like this:
.
.
.
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= render 'shared/error_messages', object: resource %>
<div class="invisible">
<%= resource.build_profile %>
</div>
<%= f.fields_for :profile do |profile_form| %>
<%= profile_form.label :full_name %>
<%= profile_form.text_field :name %>
<% end %>
<%= f.label :email %>
<%= f.email_field :email %>
.
.
.
Hope this solves someone else's problem as well!
Thank you!
This question is already answered, but I thought I'd throw this up as an alternative for others. Form backing objects can be used to go back to a one form/one model kind of setup and help keep code cleaner.
Here's a good writeup on it:
http://pivotallabs.com/form-backing-objects-for-fun-and-profit/
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|%>
?
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.
I'm tring to set values for two models that have a has_one association using accepts_nested_attributes_for, but nothing in the fields_for is being shown on the view.
I have confirmed the same code works on Rails 2.x, and it works fine when its a has_many.
Code below.
Model
class Parent < ActiveRecord::Base
has_one :child
accepts_nested_attributes_for :child
end
class Child < ActiveRecord::Base
belongs_to :parent
end
Controller
def new
#parent = Parent.new
#parent.build_child
end
View
<%= form_for #parent do |f| %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<% f.fields_for :child do |builder| %>
<%= builder.label :childname %>
<%= builder.text_field :childname %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
..And after copying that and looking at it, that's a horrible class name.
In rails 3 you should use (notice the equal sign in <%=):
<%= f.fields_for [...]
instead of :
<% f.fields_for
same goes with form_for