I need a button such that when I click it, the name attribute must be be updated in user table and an address must be saved in address table. address table belongs to user table. Now my error is that when I click submit button i am not able to save the address but my name gets updated in the user table. Can anyone help with it?
Controller Code
class ProfileController < ApplicationController
before_action :set_user, only: %i[index update_profile]
def index; end
def create
@address = Address.new(address_params)
respond_to do |format|
puts'-=-==-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-='
if @address.save
format.html { redirect_to profile_index_path, notice: 'Address was successfully created.' }
else
format.html { render :new }
end
end
end
def update_profile
respond_to do |format|
if @user.update(user_params)
format.html { redirect_to profile_index_path, notice: 'Profile was successfully updated.' }
else
format.html { render :index }
end
end
end
private
def set_user
@user = User.find(current_user.id)
@user.address || @user.build_address
end
def user_params
params.require(:user).permit(:name, address_attributes: %i[area state country])
end
def address_params
params.require(:address).permit(address: %i[area state country])
end
end
Model
address.rb
class Address < ApplicationRecord
belongs_to :user
end
user.rb
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_one :address, dependent: :destroy
validates :name, presence: true
def admin?
true
end
end
View Code
<%= form_for(@user, url: { action: 'update_profile' }, html: { class: 'm-form m-form--fit m-form--label-align-right' } ) do |f| %>
<% if @user.errors.any? %>
<h4><%= pluralize(@user.errors.count, "error") %>
prohibited this profile from being saved:</h4>
<ul>
<% @user.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
<% end %>
<div class="form-group m-form__group row">
<label for="name" class="col-2 col-form-label">
Name
</label>
<div class="col-7">
<%= f.text_field :name, class: 'form-control m-input', placeholder: 'Full Name' %>
</div>
</div>
<div class="m-form__seperator m-form__seperator--dashed m-form__seperator--space-2x"></div>
<%= f.fields_for @user.address do |a| %>
<div class="form-group m-form__group row">
<label for="example-text-input" class="col-2 col-form-label">
Address
</label>
<div class="col-7">
<%= a.text_field :area, class: 'form-control m-input', placeholder: 'Address' %>
</div>
</div>
<div class="form-group m-form__group row">
<label for="example-text-input" class="col-2 col-form-label">
City
</label>
<div class="col-7">
<%= a.text_field :city, class: 'form-control m-input', placeholder: 'City' %>
</div>
</div>
<div class="form-group m-form__group row">
<label for="example-text-input" class="col-2 col-form-label">
State
</label>
<div class="col-7">
<%= a.text_field :state, class: 'form-control m-input', placeholder: 'State' %>
</div>
</div>
<% end %>
<%= f.submit 'Save Changes', class: 'btn btn-accent m-btn m-btn--air m-btn--custom' %>
<%= link_to 'Back', root_path, class: 'btn btn-secondary m-btn m-btn--air m-btn--custom' %>
routes.rb
resources :profile do
collection do
patch 'update_profile'
get 'update_profile'
end
end
Terminal log
Started PATCH "/profile/update_profile" for 127.0.0.1 at 2018-05-07 12:33:15 +0530
Processing by ProfileController#update_profile as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"AJZaELC5GwhOsBCKRZMQMpKySMxNpIIHgNpFBuS1KbBFSs61ByG7RAxVXV8Rd7QXaQ7Htzgyty4Z1uclocXOhQ==", "user"=>{"name"=>"Karthi", "email"=>"suriya@gmail.com", "address"=>{"area"=>"L1, 54th St. & 9th Ave. Ashok Nagar", "city"=>"Chennai", "state"=>"Tamil Nadu", "country"=>"India", "postcode"=>"600083"}}, "commit"=>"Save Changes"}
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 7 ORDER BY `users`.`id` ASC LIMIT 1
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 7 LIMIT 1
Address Load (0.3ms) SELECT `addresses`.* FROM `addresses` WHERE `addresses`.`user_id` = 7 LIMIT 1
Unpermitted parameter: :address
(0.1ms) BEGIN
(0.2ms) COMMIT
Redirected to http://localhost:3000/profile
Completed 302 Found in 7ms (ActiveRecord: 1.2ms)
Started GET "/profile" for 127.0.0.1 at 2018-05-07 12:33:15 +0530
Processing by ProfileController#index as HTML
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 7 ORDER BY `users`.`id` ASC LIMIT 1
User Load (0.2ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 7 LIMIT 1
Address Load (0.2ms) SELECT `addresses`.* FROM `addresses` WHERE `addresses`.`user_id` = 7 LIMIT 1
Rendering profile/index.html.erb within layouts/application
Rendered profile/_profile_card.html.erb (0.3ms)
Rendered profile/_profile_detail.html.erb (1.7ms)
Rendered profile/index.html.erb within layouts/application (3.4ms)
Rendered layouts/_web_font.html.erb (0.3ms)
Rendered layouts/_google_analytics.html.erb (0.2ms)
Rendered layouts/_header.html.erb (1.8ms)
Rendered layouts/_alerts.html.erb (0.4ms)
Completed 200 OK in 32ms (Views: 28.7ms | ActiveRecord: 0.7ms)
I have omitted a few methods unrelated to the error and made some changes to the controller:
class ProfileController < ApplicationController
def create
@address = Address.new(address_params)
respond_to do |format|
if @address.save
format.html { redirect_to profile_index_path, notice: 'Address was successfully created.' }
else
format.html { render :new }
end
end
end
def update_profile
respond_to do |format|
if @user.update(user_params)
format.html { redirect_to profile_index_path, notice: 'Profile was successfully updated.' }
else
format.html { render :index }
end
end
end
private
def user_params
# changed `address_attributes` to `address` as the params in request contains key `address`
params.require(:user).permit(:name, address: %i[area state country])
end
def address_params
# permit the attributes directly instead of nesting them under another `address` key
params.require(:address).permit(*%i[area state country])
end
end
Let me know if it doesn't work.