nested_form / cocoon:孩子们没有保存

时间:2014-05-11 23:23:43

标签: ruby-on-rails ruby-on-rails-4 nested-forms cocoon-gem

在我的应用中,我有联系人,其中有很多目标(目标属于联系人)。我使用嵌套表单为两个模型创建/更新数据,但是在创建/更新操作期间只保存第一个子目标,这可以从下面传递的参数中看出:

Started PATCH "/contacts/2" for 127.0.0.1 at 2014-05-11 19:10:40 -0400
Processing by ContactsController#update as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"wKgOPegIJOFyrrLAnbdD67qqATFXrPNqMIT7I/tpNfo=", "contact"=>{"name"=>"Steven Tyler", "title"=>"Manager", "company"=>"Dell", "email"=>"steve@dell.com", "notes"=>"cool guy", "goals_attributes"=>{"0"=>{"title"=>"goal1", "due_date(1i)"=>"2014", "due_date(2i)"=>"5", "due_date(3i)"=>"11", "notes"=>"fdfsd", "_destroy"=>"false", "id"=>"13"}}}, "commit"=>"submit", "id"=>"2"}
  Contact Load (0.1ms)  SELECT  "contacts".* FROM "contacts"  WHERE "contacts"."id" = ? LIMIT 1  [["id", 2]]
   (0.1ms)  begin transaction
  Goal Load (0.3ms)  SELECT "goals".* FROM "goals"  WHERE "goals"."contact_id" = ? AND "goals"."id" IN (13)  [["contact_id", 2]]
   (0.1ms)  commit transaction
Redirected to http://localhost:3000/contacts/2

以下是我的模特:

class Contact < ActiveRecord::Base

  belongs_to :user
  has_many :goals, dependent: :destroy
  accepts_nested_attributes_for :goals, allow_destroy: true, reject_if: lambda {|attributes| attributes['title'].blank? && attributes['notes'].blank?}
  validates_presence_of :user_id,:name,:title,:email
end

class Goal < ActiveRecord::Base

  belongs_to :contact
  validates_presence_of :title, :due_date
end

并且,Contacts控制器中的强参数:

def contact_params
      params.require(:contact).permit(:name, :title, :company, :email, :notes, goals_attributes: [:title, :due_date, :notes, :contact_id, :_destroy, :id])
    end

以下是使用的两种表格:https://gist.github.com/nowgeez/5fbe99e814330c1b371c 知道为什么只保存第一个目标,而不是在表格中创建任何其他后续目标?在此先感谢您的帮助。

2 个答案:

答案 0 :(得分:3)

如文档中所述,使用正确的div嵌套非常重要。

所以在你的情况下你应该写:

<%= simple_form_for(@contact) do |f| %>

  <%= f.input :name %>
  <%= f.input :title %>
  <%= f.input :company %>
  <%= f.input :email %>
  <%= f.input :notes %>

  <h3>Goals:</h3>
  <div id="goals">
    <%= f.simple_fields_for(:goals) do |goal| %>
      <%= render 'goal_fields', :f => goal %>
    <% end %>  
    <div class="links">          
      <%= link_to_add_association 'add goal', f, :goals %>
    </div>
  </div>

  <%= f.submit :submit %>

<% end %>

为清楚起见,我删除了错误块。 目标本身应该包含在div中,以便删除工作。

<div class="nested-fields>
  <%= f.input :title %>
  <%= f.input :due_date %>
  <%= f.input :notes %>

  <%= link_to_remove_association "remove goal", f %>
</div>

在旁注:我讨厌写erb,它更冗长,从你的要点来看它似乎是正确嵌套的,但实际上并非如此。哈姆尔非常清楚。 只是为了证明我的观点,就像haml中的上述形式一样:

= simple_form_for @contact do |f|
  = f.input :name
  = f.input :title
  = f.input :company
  = f.input :email
  = f.input :notes

  %h3 Goals
  #goals
    = f.simple_fields_for :goals do |goal|
      = render 'goal_fields', :f => goal
    .links
      = link_to_add_association 'add goal', f, :goals
  = f.submit

但我明白这是一个品味问题。

答案 1 :(得分:0)

在您的请求中,只有一个目标

"goals_attributes"=>{"0"=>{"title"=>"goal1", "due_date(1i)"=>"2014", "due_date(2i)"=>"5", "due_date(3i)"=>"11", "notes"=>"fdfsd", "_destroy"=>"false", "id"=>"13"}}}

我猜你在使用强参数做错了,把它改成这样的东西:

def contact_params
  params.require(:contact)
  .permit(:name, :title, :email, :company, :notes,
   goal_attributes: [:title, :due_date, :notes, :_destroy, :id])
end