rails 4嵌套表单belongs_to association

时间:2015-10-11 09:41:25

标签: ruby-on-rails

我有3个表,包括嵌套表单关联,如下面的模型所示,在尝试保存时,它不会保存在Phone表中。

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

和在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

注意=&gt; 我的Activity表中有customer_id,phone_id只是为了表现

在Activity _form

 <!-- Nested form customer -->
    <%= f.fields_for :customer do |builder| %>
      <%= render "customer_fields", x: builder %>
    <% end %>

在客户部分

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

在最后一部电话中

<%= f.label :phone_number %>
<%= f.text_field :phone_number %>

为什么我无法在此嵌套

中保存电话

2 个答案:

答案 0 :(得分:3)

根据Zozo的回答,您需要按如下方式构建关联对象:

def new
    @activity = Activity.new
    @activity.build_customer.phones.build
end

您需要考虑一个额外的步骤...您在phone字段中嵌入了customer字段。这意味着您必须构建关联模型:

#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

如果你想像你一样嵌入fields_for,那么这只是

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

要做到这一点,你必须将关联数据构建为单独的对象:

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

我差点忘了,还有别的......

<% 3.times do %>
    <%= render "customers/phone_fields", f: builder %>
<% end %>

非常糟糕的做法。

如果要加载3组fields_for,则需要构建对象3次,例如:

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

答案 1 :(得分:1)

Activity.newCustomer.newPhone.new创建相应类的实例,不将它们保存到数据库中。要在操作创建的对象后执行此操作,您必须调用save方法。例如@activity.save