I have the following User controller:
class UsersController < ApplicationController
def index
@users = User.all
end
def new
@user = User.new
end
def create
@user = User.new(user_params)
@customer = Customer.new
if @user.save
flash.notice = "User '#{@user.email}' was succefully created."
redirect_to user_path(@user)
else
render 'new'
end
end
def show
@user = User.find(params[:id])
end
private
def user_params
params.require(:user).permit(:email, :password, :password_confirmation, customer_attributes: [:id, :company])
end
end
And I have the following User model:
class User < ActiveRecord::Base
has_one :customer
accepts_nested_attributes_for :customer, :allow_destroy => true
end
And the following Customer model:
class Customer < ActiveRecord::Base
belongs_to :user
end
Finally, here is the form:
<%= 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 |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<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 %><br>
<%= f.password_field :password_confirmation %>
</div>
<%= f.fields_for :customers do |company| %>
<div class="field">
<%= company.label :company %><br>
<%= company.text_field :company %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
When I submit the form, I see: `Unpermitted parameters: customers' in the log but it appears that I m indeed permitting it.
Also, I want to show the company name for each user in the show and index views. I'm not sure how to do that.
I remember using the build
method in the past to get something similar to work but I can't seem to figure it out this time.
Further to @Mandeep
's answer, let me give you some further information:
- You need to "build" your associated objects for your form
- You need to process this as per the association your model has
- You need to save the attributes as per said association
The way to do this is relatively simple (outlined by Mandeep
). However, the reason why might be a little less obvious:
Build
First, you need to build your associative association. This is vitally important, primarily because Rails (by virtue of being built on Ruby), is an object orientated framework.
Object orientation, without getting into too much detail, means that everything you do with Rails is going to be based around objects. In the case of our beloved Rails, it means that every Model
is an object
.
By virtue of this fact, the nested model paradigm has to be built in Rails whenever you want to create such a form. To do this, you need to use the build
methods - which tell ActiveRecord (Rails' object relational mapper) that you have another associated model / object which you want to populate:
#app/controllers/users_controller.rb
class UsersController < ApplicationController
def new
@user = User.new #-> initializes "User" object
@user.build_customer #-> "builds" the associated object
end
end
This gives Rails a set of associated data which it can populate with your form (considering you call the correct methods)
--
Association
Second, you need to consider the association you have. This is important as singular & multiple associations are handled differently in the "build" process.
You're using a has_one
relationship, which means you need to use singular association names (although you can call the associations whatever you want):
If you used a has_many
association, you'd need to use the plural association methods:
This explains the need to use the build_customer
method; but also should give you the presidence to use the singular association name for all the methods you need to get this working, namely fields_for
and params
:
#app/views/users/new.html.erb
<%= form_for @user do |f| %>
...
<%= f.fields_for :customer do |c| %>
...
<% end %>
<%= f.submit %>
<% end %>
#app/controllers/users_controller.rb
class UsersController < ApplicationController
def create
@user = User.new user_params
@user.save
end
private
def user_params
params.permit(:user).permit(:user, :params, customer_attributes: [:x. :y])
end
end
--
Save
The above controller code will save the attributes you require.
You must understand that passing nested attributes means that the model you're sending the associative data to needs to be subordinated to your "main" model. This happens with the ActiveRecord associations
in your models, as discussed initially.
Hopefully this gives you some more clarity
Change your code to this:
def new
@user = User.new
@user.build_customer
end
your form:
<%= form_for @user do |f| %>
// user fields
<%= f.fields_for :customer do |customer| %>
// customer fields
<% end %>
<% end %>
Also there is not need of @customer = Customer.new in your create method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With