Reputation: 989
I have 3 tables, including nested form association as shown in the following models and while try to save,it doesn't save in Phone table.
class Activity < ActiveRecord::Base
belongs_to :customer
belongs_to :phone
accepts_nested_attributes_for :customer
accepts_nested_attributes_for :phone, reject_if: proc { |attributes| attributes['N'].blank? }
end
class Customer < ActiveRecord::Base
has_many :phones, dependent: :destroy
has_many :activities
accepts_nested_attributes_for :phones, reject_if: proc { |attributes| attributes['phone_number'].blank? }, allow_destroy: true
accepts_nested_attributes_for :activities
end
class Phone < ActiveRecord::Base
belongs_to :customer
has_many :activities
accepts_nested_attributes_for :activities
end
and in ActivitiesController
def new
@activity = Activity.new
@activity.customer = Customer.new
@activity.phone = Phone.new
end
def activity_params
params.require(:activity).permit(:activityDate, :customer_id, :phone_id, :details, customer_attributes: [:id, :name, phone_attributes: [:id, :phone_number]])
end
Note => I have in my Activity table customer_id, phone_id just for performance
in Activity _form
<!-- Nested form customer -->
<%= f.fields_for :customer do |builder| %>
<%= render "customer_fields", x: builder %>
<% end %>
in customer partial
<div class="field form-group">
<%= x.label "Customer name" %>
<%= x.text_field :name, class: 'form-control' %>
</div>
<%= x.fields_for :phone do |builder| %>
<% 3.times do %>
<%= render "customers/phone_fields", f: builder %>
<% end %>
<% end %>
in the last phone partial
<%= f.label :phone_number %>
<%= f.text_field :phone_number %>
Why I can't save Phones in this nested
Upvotes: 3
Views: 949
Reputation: 76784
As per Zozo
's answer, you'll need to build the associated objects as follows:
def new
@activity = Activity.new
@activity.build_customer.phones.build
end
There's an added step you need to consider... you're embedding your phone
fields inside your customer
fields. This means that you'll have to build the associative models as they are associated:
#app/models/activity.rb
class Activity < ActiveRecord::Base
belongs_to :phone
belongs_to :customer
accepts_nested_attributes_for :customer
end
#app/models/customer.rb
class Customer < ActiveRecord::Base
has_many :phones
accepts_nested_attributes_for :phones
end
This is only necessary if you want to embed the fields_for
like you have:
#app/controllers/activities_controller.rb
class ActivitiesController < ApplicationController
def new
@activity = Activity.new
@activity.build_customer.phones.build
end
def create
@activity = Activity.new activity_params
@activity.save
end
private
def activity_params
params.require(:activity).permit(:x, :y, :z, customer_attributes:[ phones_attributes: [:phone, :attributes] ])
end
end
#app/views/activities/new.html.erb
<%= form_for @activity do |f| %>
<%= f.fields_for :customer do |x| %>
<%= x.fields_for :phones do |phones| %> #-> see how you're embedding this inside the original fields_for?
<%= phones.text_field %>
<% end %>
<% end %>
<% end %>
To do it normally, you'd have to just build the associative data as separate objects:
#app/models/activity.rb
class Activity < ActiveRecord::Base
belongs_to :customer
belongs_to :phone
accepts_nested_attributes_for :customer, :phone
end
#app/controllers/activities_controller.rb
class ActivitiesController < ApplicationController
def new
@activity = Activity.new
@activity.build_customer
@activity.build_phone
end
end
#app/views/activities/new.html.erb
<%= form_for @activities do |f| %>
<%= f.fields_for :customer do |customer| %>
<%= customer.text_field .... %>
<% end %>
<%= f.fields_for :phone do |phone| %>
<%= phone.text_field .... %>
<% end %>
<% end %>
I almost forgot, there's something else...
<% 3.times do %>
<%= render "customers/phone_fields", f: builder %>
<% end %>
VERY BAD PRACTICE.
If you want 3 sets of fields_for
to load, you need to build the object 3 times, eg:
def new
@activity = Activity.new
3.times do
@activity.build_phone
end
end
<%= form_for @activity do |f| %>
<%= f.fields_for :phone do |f| %>
This will appear 3 times
<% end %>
<% end %>
Upvotes: 3
Reputation: 1183
Activity.new
, Customer.new
and Phone.new
create instances of the respective classes and don't save them to the database. To do that after manipulating the created objects you have to call save
method. For example @activity.save
.
Upvotes: 1