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|%>
?
Related
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
I'm and usings devise for my authentication and would like to keep the details of my users in a separate model called profile. Profile contains information like first and last name. I want to be able to have a single sign up form that will be able to have all this information entered.
This is my form
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= render 'shared/error_messages' %>
<% fields_for :profile do |fa| %>
<%= fa.label :first_name %>
<%= fa.text_field :first_name %>
<%= fa.label :last_name %>
<%= fa.text_field :last_name %>
<% 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 in my user.rb model
has_one :profile
accepts_nested_attributes_for :profile
When I submit the from it doesn't save the first and last name to the database
After much searching around, this was the simplest answer to my question. Although I'm not sure this the rails way of doing things
Profile model for Devise users?
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 %>
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.
How to create form for new User model with embedded Phone model?
I've found solution for creating form to add Phone for existing User but how to do that at the same time i create new User?
You have to create a nested form
<%= form_for #user, :url => users_path do |f| %>
<%= f.label :name, "Name:" %> <br />
<%= f.text_field :name %>
<%= f.fields_for :phone do |p| %>
<%= p.label :number, "Phone Number" %> <br />
<%= p.text_field :number %>
<% end %>
<% end %>