I am stuck in a situation where I need to give prefilled data for the fields_for with an empty form. Let me explain with an example
Association
class User < ApplicationRecord
has_one :account, foreign_key: :user_id
accepts_nested_attributes_for :account
end
Class Account
belongs_to :user
end
Now I have a form on the dashboard index page.
<%= form_for @account, :url => account_path, html: { class: "abc" } do |f| %>
<%= f.hidden_field :user_id, :value => current_user.id %>
<%= f.fields_for :user do |user| %>
<div class="medium-4 columns">
<label>First Name</label>
<%= user.text_field :first_name , class: 'xyz', data: {input: 'someinput'} %>
</div>
<div class="medium-4 columns">
<label><b>Last Name<span class="invalid_message"> This field is required</span></b></label>
<%= user.text_field :last_name, class: 'xyz', data: {input: 'someinput'} %>
</div>
<% end %>
<div class="medium-4 medium-offset-2 columns">
<label>Phone Number</label>
<%= f.text_field :phone_number, class: 'xyz', data: {input: 'someinput'} %>
</div>
<% end %>
Controller
class AccountsController < ApplicationController
def create
@account = Account.new(account_params)
if @account.save
render json: {status: 'successfull'}
else
render json: {error: "#{@account.errors.full_messages}"}, status: 400
end
end
private
def account_params
params.require(:account).permit(:phone_number, :user_id, user_attributes: [:first_name, :last_name])
end
end
class DashboardController < ApplicationController
def index
##I will always have current_user. For the account it will be blank for the first time
if current_user.account.blank?
@account = Account.new
else
@account = current_user.account
end
end
end
Parameters
{"utf8"=>"✓", "authenticity_token"=>"asdasdadadadadsadadadadadQpy0tA82asdaalAgJsUcNk1i/kGETfZqnuQA==", "account"=>{"user_id"=>"123", "user"=>{"first_name"=>"sd", "last_name"=>"ad"}, "phone_number"=>"1212"}}
There are two issues
1) First and Last name are not getting prefilled
2) Params are not going correctly. It should be account_attributes instead of account in the parameter.
Note: In my case, @account will be blank for the first time but still user object(which is the current user) has first_name and last_name already wHich I need to prefill in the fields_for. Also, I need a way to update the first and last name
Can anyone tell me where I am doing wrong
Finally, I found the solution. I was doing a couple of things wrong
1) In form_for it should be @user instead of @account
2) Then in the controller this form will always send it to update action instead of create. The reason is I will always have current_user so rails will automatically check if the object(current_user) exists so instead of sending to create it will send to update action
3) Lastly, when working with one to one assocation we need to load the parent object and build the child object.
<%= form_for @user, :url => user_path, html: { class: "abc" } do |f| %>
<div class="medium-4 columns">
<label>First Name</label>
<%= f.text_field :first_name , class: 'xyz', data: {input: 'someinput'} %>
</div>
<div class="medium-4 columns">
<label><b>Last Name<span class="invalid_message"> This field is required</span></b></label>
<%= f.text_field :last_name, class: 'xyz', data: {input: 'someinput'} %>
</div>
<%= f.fields_for :account do |account_info| %>
<div class="medium-4 medium-offset-2 columns">
<label>Phone Number</label>
<%= account_info.text_field :phone_number, class: 'xyz', data: {input: 'someinput'} %>
</div>
<% end %>
<% end %>
class UsersController < ApplicationController
def update
if current_user.update(account_params)
render json: {status: 'successfull'}
else
render json: {error: "#{@account.errors.full_messages}"}, status: 400
end
end
private
def account_params
params.require(:account).permit(:first_name, :last_name, account_attributes: [:phone_number])
end
end
class DashboardController < ApplicationController
def index
##I will always have current_user. For the account it will be blank for the first time
if current_user.account.blank?
@account = current_user
@account.build_account
end
end
end