Rails 5: accepts nested attributes for - ruby-on-rails

I'm trying to implement accepts_nested_attributes_for on my app. When I add accepts_nested_attributes_for :account to the user.rb the nested fields disappear. When I delete accepts_nested_attributes_for :account the fields appear but no data is being saved when I click on submit.
Any ideas why this is happening?
I have two models with appropriate associations added:
user.rb
has_one :account
has_many :items
accepts_nested_attributes_for :account
account.rb
belongs_to :user
app/controllers/users/registrations.controller.rb
before_action :configure_permitted_parameters, if: :devise_controller?
def new
build_resource({})
resource.build_account
respond_with self.resource
session[:registration_params] = request.query_parameters
end
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up) { |u|
u.permit(:email, :password, :password_confirmation, :remember_me,
:account_attributes => [:first_name, :last_name, :buisness_name,
:buisness_description, :web_site, :phone_number,
:street, :city, :state, :zip_code, :country])
}
end
new.html.erb
<h2>Sign up</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<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>
<%= f.fields_for :account do |form| %>
<div class="field">
<%= form.label :first_name %>
<%= form.text_field :first_name, id: :account_first_name %>
</div>
<div class="field">
<%= form.label :last_name %>
<%= form.text_field :last_name, id: :account_last_name %>
</div>
<div class="field">
<%= form.label :buisness_name %>
<%= form.text_field :buisness_name, id: :account_buisness_name %>
</div>
<div class="field">
<%= form.label :buisness_description %>
<%= form.text_field :buisness_description, id: :account_buisness_description %>
</div>
<div class="field">
<%= form.label :web_site %>
<%= form.text_field :web_site, id: :account_web_site %>
</div>
<div class="field">
<%= form.label :phone_number %>
<%= form.text_field :phone_number, id: :account_phone_number %>
</div>
<div class="field">
<%= form.label :street %>
<%= form.text_field :street, id: :account_street %>
</div>
<div class="field">
<%= form.label :city %>
<%= form.text_field :city, id: :account_city %>
</div>
<div class="field">
<%= form.label :state %>
<%= form.text_field :state, id: :account_state %>
</div>
<div class="field">
<%= form.label :zip_code %>
<%= form.text_field :zip_code, id: :account_zip_code %>
</div>
<div class="field">
<%= form.label :country %>
<%= form.text_field :country, id: :account_country %>
</div>
<% end %>
<div class="actions">
<%= f.submit "Sign up" %>
</div>
<% end %>

I had to add the controller to routes.rb devise_for :users
devise_for :users, controllers: {registrations: 'users/registrations'}

You can use cocoon gem for nested attributes. It will make handling nested attributes lot more easier

Related

Problem with nested attributes for Devise registration page

I need to add Address nested attributes for User.
But only user_id hits the addresses table when I submit, and not country city street and zip_code
user.rb
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
validates_presence_of :name, :age, :email
has_one :address, dependent: :destroy
accepts_nested_attributes_for :address
address.rb
attr_accessor :country, :city, :zip_code, :street
belongs_to :user
appication_controller.rb
before_action :configure_permitted_parameters, if: :devise_controller?
...
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:name, :age,
address_attributes: [:country, :city, :zip_code, :street]])
end
The form
<% resource.build_address %>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
<div class="form-group">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email", class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :name %><br />
<%= f.text_field :name, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :age %><br />
<%= f.number_field :age, class: 'form-control' %>
</div>
<h4>Address</h4>
<%= f.fields_for :address do |address| %>
<div class="form-group">
<%= address.label :country %>
<%= address.text_field :country, class: 'form-control' %>
</div>
<div class="form-group">
<%= address.label :city %>
<%= address.text_field :city, class: 'form-control'%>
</div>
<div class="form-group">
<%= address.label :street %>
<%= address.text_field :street, class: 'form-control'%>
</div>
<div class="form-group">
<%= address.label :zip_code %>
<%= address.text_field :zip_code, class: 'form-control' %>
</div>
<% end %>
<div class="form-group">
<%= f.label :password %>
<% if #minimum_password_length %>
<em>(<%= #minimum_password_length %> characters minimum)</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "new-password", class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "new-password", class: 'form-control' %>
</div>
<div class="form-group">
<%= f.submit "Sign up", class: 'btn btn-success' %>
</div>
<% end %>

How to Force the User to Complete the Whole Form?

I am creating a Sing Up form. I need the user to complete every field of the form, but the rails only blocks the creation when there is no password. What I have to do to force the user to complete the whole form before submiting?
Here's my form code:
<%= form_for(user) do |f| %>
<% if user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(user.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% user.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :first_name %>
<%= f.text_field :first_name %>
</div>
<div class="field">
<%= f.label :last_name %>
<%= f.text_field :last_name %>
</div>
<div class="field">
<%= f.label :email %>
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :password %>
<%= f.password_field :password %>
</div>
<div class="field">
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation %>
</div>
<div class="field">
<%= f.label :fav_team, "Favorite Team" %>
<%= collection_select(:user, :fav_team, League.order(:name), :id, :name, {:include_blank => "Select a League"}, { :id => "leagues_select"}) %>
<%= grouped_collection_select(:user, :fav_team, League.order(:name), :teams, :name, :id, :name, {:include_blank => true}, {}) %>
</div>
<div class="field">
<%= f.label :net_worth, "Net Worth (USD)" %>
<%= f.text_field :net_worth, :readonly => true, :value => "100" %>
</div>
<div class="field">
<%= f.label :country %>
<%= f.select :country, options_for_Countrys, :include_blank => true %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
You have to write validations in your models to make sure the data is valid and present.
In your case you have to do something like this
class User < ApplicationRecord
validates :first_name, presence: true, length: { maximum: 50 }
validates :last_name, presence: true, length: { maximum: 50 }
end
You can check here for more information

How to add polymorphic address to devise custom registration controller?

I'm trying to setup a custom registration controller using Devise and a polymorphic address model, but can't seem to actually get the address to save to the database.
Here is my controller:
class RegistrationsController < Devise::RegistrationsController
before_action :configure_permitted_parameters, if: :devise_controller?
def new
build_resource({})
resource.build_address
respond_with self.resource
end
def create
super
end
private
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up) {|u|
u.permit(:first_name,:last_name,:mobile,:landline,:email,:password,:password_confirmation, :current_password, address_attributes: [:line_1,:line_2,:city,:region,:post_code,:country])
}
end
end
my user model:
class User < ApplicationRecord
devise :database_authenticatable, :registerable,:recoverable, :rememberable, :trackable, :validatable
has_one :address, through: :addressable
accepts_nested_attributes_for :address
... (other attributes)
my address model:
class Address < ApplicationRecord
belongs_to :addressable, polymorphic: true
end
relevant part of routes:
devise_for :users, :controllers => {registrations: 'registrations'}
devise_scope :user do
get '/login', to: 'devise/sessions#new'
get '/logout', to: 'devise/sessions#destroy'
get '/signup', to: 'devise/registrations#new'
end
and finally the relevant part of the view view:
<%= 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>
<%= fields_for :address do |ff| %>
<div class="field">
<%= ff.label :line_1 %>
<%= ff.text_field :line_1 %>
</div>
<div class="field">
<%= ff.label :line_2 %>
<%= ff.text_field :line_2 %>
</div>
<div class="field">
<%= ff.label :city %>
<%= ff.text_field :city%>
</div>
<div class="field">
<%= ff.label :region%>
<%= ff.text_field :region%>
</div>
<div class="field">
<%= ff.label :post_code%>
<%= ff.text_field :post_code %>
</div>
<div class="field">
<%= ff.label :country %>
<%= ff.text_field :country%>
</div>
<% end %>
<div class="field">
<%= f.label :mobile %><br/>
<%= f.text_field :mobile, autofocus: true %>
</div>
<div class="field">
<%= f.label :landline %><br/>
<%= f.text_field :landline, 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", class: "btn btn-default" %>
</div>
<% end %>
Any help would be much appreciated! :)

How to create a profile for devise user?

I'm new to rails and trying to create a profile for devise users when they signup, using nested form in devise signup. I've gone through
Creating Profile for Devise users,
Profile model for Devise users?
and few other articles to achieve the same but after a day in vain, I'm still trying to make it work. Here is my code.
Model - user.rb
class User < ActiveRecord::Base
has_one :user_profile
accepts_nested_attributes_for :user_profile
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
Model - user_profile.rb
class UserProfile < ActiveRecord::Base
belongs_to :user
end
Controller - controllers/users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) {|u|
u.permit(:email, :password, :password_confirmation, :remember_me,
user_profile_attributes: [:first_name, :last_name])}
end
end
end
View - views/devise/registrations/new.html.erb
<h2>Sign up</h2>
<% resource.build_user_profile %>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<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>
<%= f.fields_for :user_profile do |profile_form| %>
<%= profile_form.label :first_name %><br/>
<%= profile_form.text_field :first_name %><br/>
<%= profile_form.label :last_name %><br/>
<p><%= profile_form.text_field :last_name %><br/>
<% end %>
<div class="actions">
<%= f.submit "Sign up" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
Server Log
Processing by Devise::RegistrationsController#create as HTML
Parameters: {"utf8"=>"√", "authenticity_token"=>"rLuFXwISxiJpWPjpmKzjnjhKr41F5
56sWbtT+8gslAMsFDWRbl7MSitSXUESjLdZccCBGBGvVv+JbhW7G5py5g==", "user"=>{"email"=>
"zebandz#gmail.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTER
ED]", "user_profile_attributes"=>{"first_name"=>"Zeban", "last_name"=>"Dezend"}}
, "commit"=>"Sign up"}
Unpermitted parameter: user_profile_attributes
I think, I'm missing the code to fetch the values from params and create a new record. Can someone suggest me the fix ?
please follow the below steps.
devise> reg > new
<div class="row">
<div class="col-md-5 col-md-offset-4">
<h2>Sign up</h2>
<% resource.build_user_profile if resource.user_profile.nil? %>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div class="row">
<%= f.fields_for :user_profile do |profile_form| %>
<div class="col-md-6">
<div class="form-group">
<%= profile_form.label :first_name %>
<%= profile_form.text_field :first_name, class: "form-control" %>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<%= profile_form.label :last_name %>
<%= profile_form.text_field :last_name, class: "form-control" %>
</div>
</div>
<% end %>
</div>
<div class="form-group">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, class: "form-control" %>
</div>
<%= f.fields_for :user_profile do |profile_form| %>
<div class="form-group">
<%= profile_form.label :business_name %>
<%= profile_form.text_field :business_name, class: "form-control" %>
</div>
<div class="form-group">
<%= profile_form.label :business_category %>
<%= profile_form.collection_select :business_category_id, BusinessCategory.all, :id, :name, {prompt: "Select Category"}, {class: "form-control"} %>
</div>
<div class="form-group">
<%= profile_form.label :website %>
<%= profile_form.url_field :website, class: "form-control" %>
</div>
<div class="form-group">
<%= profile_form.label :address %>
<%= profile_form.text_area :address, class: "form-control" %>
</div>
<div class="form-group">
<%= profile_form.label :personal_number %>
<%= profile_form.text_field :phone_number, class: "form-control" %>
</div>
<div class="form-group">
<%= profile_form.label :office_number %>
<%= profile_form.text_field :office_number, class: "form-control" %>
</div>
<% end %>
<div class="form-group">
<%= f.label :password %>
<% if #minimum_password_length %>
<em>(<%= #minimum_password_length %> characters minimum)</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "off", class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "off", class: "form-control" %>
</div>
<div class="actions">
<%= f.submit "Sign up", class: "btn btn-primary" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
</div>
</div>
user reg controller
def new
# Override Devise default behaviour and create a profile as well
build_resource({})
resource.build_user_profile
respond_with self.resource
end
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up) { |u|
u.permit(:email, :password, :password_confirmation, :user_profile_attributes => [:first_name, :last_name, :business_name, :business_category_id, :website, :address, :phone_number, :office_number])
}
end
Have you tried following these steps from their github page?
They set the permitted parameters in the ApplicationController. Also the structure is a little different. The parameters go into keys.
https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-sign-in-using-their-username-or-email-address
class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
added_attrs = [:username, :email, :password, :password_confirmation, :remember_me]
devise_parameter_sanitizer.permit :sign_up, keys: added_attrs
devise_parameter_sanitizer.permit :account_update, keys: added_attrs
end
end

param not found: first_name | ActionController::ParameterMissing in LegaciesController#create

I am getting the error: param not found: first_name | ActionController::ParameterMissing in LegaciesController#create
On
private
def link_params
params.require(:first_name).permit(:id, :last_name, :legacy_donations, :address, :city, :state, :zip_code, :gender, :date_of_birth, :Marital_status, :Spouses_name, :comments)
end
end
This is my controller
class LegaciesController < ApplicationController
def index
end
def new
#legacy = Legacy.new
end
def create
#legacy = Legacy.new(link_params)
if #legacy.save
redirect_to #legacy
else
render action: 'new'
end
end
def show
end
def destroy
end
def edit
end
def update
end
private
def link_params
params.require(:first_name).permit(:id, :last_name, :legacy_donations, :address, :city, :state, :zip_code, :gender, :date_of_birth, :Marital_status, :Spouses_name, :comments)
end
end
And this is my legacies/new view:
%= form_for #legacy, html:{ role: "form", class: "new-legacy"} do |f| %>
<% if #legacy.errors.any? %>
<div id="error_explanation">
<h1><%= pluralize(#legacy.errors.count, "error") %> prohibited this from being saved:</h1>
<ul>
<% #legacy.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<div class="field">
<%= f.label :First_Name %><br />
<%= f.text_field :first_name, class:"form-control", placeholder:"First Name" %>
</div>
<div class="form-group">
<div class="field">
<%= f.label :Last_Name %><br />
<%= f.text_field :last_name, class:"form-control", placeholder:"Last Name" %>
</div>
<div class="form-group">
<div class="field">
<%= f.label :Last_Name %><br />
<%= f.text_field :last_name, class:"form-control", placeholder:"Last Name" %>
</div>
<div class="form-group">
<div class="field">
<%= f.label :Last_Name %><br />
<%= f.text_field :last_name, class:"form-control", placeholder:"Last Name" %>
</div>
<div class="form-group">
<div class="field">
<%= f.label :Address %><br />
<%= f.text_field :address, class:"form-control", placeholder:"Adress" %>
</div>
<div class="form-group">
<div class="field">
<%= f.label :City %><br />
<%= f.text_field :city, class:"form-control", placeholder:"City" %>
</div>
<div class="form-group">
<div class="field">
<%= f.label :State %><br />
<%= f.text_field :state, class:"form-control", placeholder:"State" %>
</div>
<div class="form-group">
<div class="field">
<%= f.label :Zip_Code %><br />
<%= f.text_field :zip_code, class:"form-control", placeholder:"Zip Code" %>
</div>
<div class="form-group">
<div class="field">
<%= f.label :Gender %><br />
<%= f.text_field :gender, class:"form-control", placeholder:"Gender" %>
</div>
<div class="form-group">
<div class="field">
<%= f.label :DOB %><br />
<%= f.date_field :date_of_birth, class:"form-control", placeholder:"DOB" %>
</div>
<div class="form-group">
<div class="field">
<%= f.label :Marital_Status %><br />
<%= f.text_field :gender, class:"form-control", placeholder:"Marital Status" %>
</div>
<div class="form-group">
<div class="field">
<%= f.label :Spouses_Name %><br />
<%= f.text_field :gender, class:"form-control", placeholder:"Spouses Name" %>
</div>
<div class="form-group">
<div class="field">
<%= f.label :Legacy_Donations %><br />
<%= f.text_field :legacy_donations, class:"form-control", placeholder:"Legacy Donations" %>
</div>
<div class="form-group">
<div class="field">
<%= f.label :Comments %><br />
<%= f.text_field :comments, class:"form-control", placeholder:"Comments" %>
</div>
<div class="actions">
<%= f.submit class:"btn btn-default new-eurekamoment-button" %>
</div>
<% end %>
</div>
Whats the deal am I overlooking something?
It should be
def link_params
params.require(:legacy).permit(:id, :first_name,:last_name, :legacy_donations, :address, :city, :state, :zip_code, :gender, :date_of_birth, :Marital_status, :Spouses_name, :comments)
end

Resources