Problem with nested attributes for Devise registration page - ruby-on-rails

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 %>

Related

Ruby on rails Active Storage Validations not working

I am using:
Rails 6.0.4.4
Ruby 3.0.0
I have added gem'active_storage_validations' to my project, and am trying to use it to validate that attached avatars are images
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable, :confirmable, :trackable, :lockable, :masqueradable
validates :first_name, :last_name, presence: true
validates :email, uniqueness: true
validates :terms_and_conditions, acceptance: true
validates :avatar, attached: true, content_type: ['image/png', 'image/jpg', 'image/jpeg']
has_one_attached :avatar
end
in my sign_up form
<%= render "devise/shared/error_messages", resource: resource %>
<div class="container pt-3 pb-3">
<div class="card">
<div class="card-header">
<h2>Sign up</h2>
</div>
<div class="card-body">
<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<div class="field mb-3">
<%= f.label :profile_picture %><br />
<%= f.file_field :avatar, class: "form-control" %>
</div>
<div class="field mb-3">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email", class: "form-control", placeholder: "name#email.com" %>
</div>
<div class="field mb-3">
<%= f.label :first_name %><br />
<%= f.text_field :first_name, required: true, autofocus: true, autocomplete: "first_name", class: "form-control" %>
</div>
<div class="field mb-3">
<%= f.label :last_name %><br />
<%= f.text_field :last_name, autofocus: true, autocomplete: "last_name", class: "form-control" %>
</div>
<div class="field mb-3">
<%= 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="field mb-3">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "new-password", class: "form-control" %>
</div>
<div class="form-check form-switch text-muted">
<%= f.check_box :terms_and_conditions, class: 'form-check-input', id: 'flexSwitchCheckDefault' %>
I hereby confirm I have read and undertood the terms and conditions
</div>
<div class="actions">
<%= f.submit "Continue", class: "btn btn-primary" %>
</div>
<% end %>
<br>
<%= render "devise/shared/links" %>
</div>
</div>
</div>
All the other validations work fine.
If I add validations for file type or size on the attached image, it still allows the user to upload any file type and size

Rails 5: accepts nested attributes for

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

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

Devise user model not updating

When I submit the user update form, I don't get any errors, but the info doesn't update.
Here is my RegistrationsController
class RegistrationsController < Devise::RegistrationsController
private
def sign_up_params
params.require(:user).permit(:username, :email, :password, :password_confirmation, :firstname, :lastname, :displayname)
end
def account_update_params
params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation, :current_password)
end
end
Here is part of my routes.rb
devise_for :users, :controllers => { registrations: 'registrations' }
Finally here is the devise/registrations/edit.html.erb
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
<%= render 'shared/error_messages' %>
<h1>Edit Your Profile</h1>
<div class="row">
<div class="col-md-4">
<h3>Social</h3>
<hr>
<div class="form-group">
<%= f.label :displayname, "Display Name" %><br>
<%= f.text_field :displayname, autocomplete: "off", class: "form-control" %>
</div>
<div class="form-group">
<div class="row">
<div class="col-md-6">
<%= f.label :firstname, "First Name" %><br>
<%= f.text_field :firstname, class: "form-control" %>
</div>
<div class="col-md-6">
<%= f.label :lastname, "Last Name" %><br>
<%= f.text_field :lastname, class: "form-control" %>
</div>
</div>
</div>
<%= f.label :twitter, "Twitter" %><br>
<div class="input-group">
<div class="input-group-addon">twitter.com/</div>
<%= f.text_field :twitter, class: "form-control" %>
</div>
<br>
<%= f.label :facebook, "Facebook" %><br>
<div class="input-group">
<div class="input-group-addon">facebook.com/</div>
<%= f.text_field :facebook, class: "form-control" %>
</div>
<br>
<%= f.label :reddit, "Reddit" %><br>
<div class="input-group">
<div class="input-group-addon">reddit.com/u/</div>
<%= f.text_field :reddit, class: "form-control" %>
</div>
<br>
<%= f.label :github, "Github" %><br>
<div class="input-group">
<div class="input-group-addon">github.com/</div>
<%= f.text_field :github, class: "form-control" %>
</div>
<br>
<%= f.label :youtube, "Youtube" %><br>
<div class="input-group">
<div class="input-group-addon">youtube.com/user/</div>
<%= f.text_field :youtube, class: "form-control" %>
</div>
<br>
<%= f.label :twitch, "Twitch" %><br>
<div class="input-group">
<div class="input-group-addon">twitch.tv/</div>
<%= f.text_field :twitch, class: "form-control" %>
</div>
</div>
<div class="col-md-4">
<h3>Login Info</h3>
<hr>
<div class="form-group">
<%= f.label :email %><br>
<%= f.email_field :email, autofocus: true, class: "form-control" %>
</div>
<% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
<div class="alert alert-warning">Currently waiting confirmation for: <%= resource.unconfirmed_email %></div>
<% end %>
<div class="form-group">
<%= f.label :password %><br>
<%= f.password_field :password, autocomplete: "off", class: "form-control" %>
<span class="help-block">Leave blank if you don't want to change it</span>
</div>
<div class="form-group"><%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, autocomplete: "off", class: "form-control" %>
</div>
<div class="form-group"><%= f.label :current_password %>
<%= f.password_field :current_password, autocomplete: "off", class: "form-control" %></div>
<span class="help-block">Please enter your current password to confirm your changes</span>
</div>
<div class="col-md-4">
<h3>Your Stats</h3>
<hr>
</div>
</div>
<br>
<div class="form-group"><%= f.submit "Update", class: "btn btn-success" %></div>
<% end %>
<%= link_to "Back", :back %>
User Model:
class User < ActiveRecord::Base
rolify
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :confirmable, :timeoutable, :lockable
#ROLES = "%w[default plus moderator administrator suspended banned]"
# BEGIN HAS_MANYS
has_many :posts
has_many :assignments
has_many :evaluations, class_name: "RSEvaluation", as: :source
has_reputation :votes, source: {reputation: :votes, of: :posts}, aggregated_by: :sum
# BEGIN METHODS
def voted_for?(post)
evaluations.where(target_type: post.class, target_id: post.urlid).present?
end
# def has_role?(role_sym)
# roles.any? { |r| r.name.underscore.to_sym == role_sym }
# end
end
I have face same problem while updating user account with rails 4, but there is problem with parameter permitted .
Please update your controller like
class RegistrationsController < Devise::RegistrationsController
before_filter :update_sanitized_params, if: :devise_controller?
def update_sanitized_params
devise_parameter_sanitizer.for(:sign_up) {|u| u.permit(:username, :email, :password, :password_confirmation, :firstname, :lastname, :displayname)}
devise_parameter_sanitizer.for(:account_update) {|u| u.permit(:first_name, :last_name, :email, :password, :password_confirmation, :current_password)}
end
end
It will work :)

Resources