开发者

Anyone know how to save many objects in one form?

开发者 https://www.devze.com 2023-01-20 15:48 出处:网络
I am trying to save many new objects in a form to one pre-existing parent object. - form_for :parent_object do |f|

I am trying to save many new objects in a form to one pre-existing parent object.

- form_for :parent_object do |f|

This is the beginning of my form. And then within it, I would do:

  - 2.times do
    - fields_for :child_object do |f|

Now if I were to save this, it would render as an ParentObject_Controller Update action which would fail because Update doesn't identify new objects.

So if I wanted to render the appropriate Save action, I would have to set up like this :

- form_for [@parent_object, @child_object] do |f|
  - 2.times do
    - fields_for :child_object do |f|

This form then renders the Save action, but only saves the last child_object.

I would show you my controller, but there's hardly a point because its devastatingly erroneous.

My question is, how would you save many new objects in a form to one pre-existing parent object?

I have looked extensively at Ryan Bate's work, and many many other blogs and SO posts regarding this. Nothing seems to really point at specifically creating new child objects for one pre-existing parent object.

Update:

I am under the impression that I have to toggle the parent_object's controller actions for def update.

  elsif params[:parent_object][:child_object]
    @child_object = Child_Object.new(params[:child_object])
    if @child_object.valid? && @parent_object.referrals << @child_object
      redirect_to new_parent_object_child_object_path(@parent_object)
    else
      render :action => :new
    end

In debugger, if I I place a debugger at开发者_Python百科 the root of def update, and I write :

>> params[:parent_object]
#=> nil

Interesting! That means that when child_object is send to parent_object controller, the params are not filled out for it. Haha, no idea what to do about it though..

Unfortunately that code doesn't work, it was just my attempt at getting closer. ;)


OK, let's give it another shot. Code taken from RB's screencast with replaced object names:

<% form_for @parent_object do |f| %>  
  <%= f.error_messages %>  
  <!-- some field of parent object here -->
  <p>  
    <%= f.label :name %><br />  
    <%= f.text_field :name %>  
  </p>  
  <% f.fields_for :child_objects do |builder| %>  
  <!-- some fields for child objects -->
  <p>  
    <%= builder.label :content, "Some content for child object" %><br />  
    <%= builder.text_area :content, :rows => 3 %>  
    <%= builder.check_box :_destroy %>  
    <%= builder.label :_destroy, "Remove child object" %>  
  </p>  
  <% end %>  
  <p><%= f.submit "Submit" %></p>  
<% end %>

This is a form for @parent_object that has fields for :child_objects. Of course, you've to replace fields with your own.

To make this work, you'll have to build child objects in the constructor:

def new  
  @parent_object = ParentObject.new  
  3.times { @parent_object.child_objects.build }  
end 

Similarly in the edit method, you'd do:

def edit  
  @parent_object = ParentObject.find(params[:id])
  3.times { @parent_object.child_objects.build }  
end

To make it work, you need to define the nested attributes for child object:

class ParentObject < ActiveRecord::Base  
  has_many :child_objects, :dependent => :destroy  
  accepts_nested_attributes_for :child_objects
end    

Hope this helps - this is exactly what RB proposes in his screencasts. Let me know in the comments if you need some further explanation.

-- EDIT --

The update method in the parent_object_controller.rb is just a standard one:

def update
  @parent_object = ParentObject.find(params[:id])
  if @parent_object.update_attributes(params[:parent_object])
    flash[:notice] = "Successfully updated parent object."
    redirect_to @parent_object
  else
    render :action => 'edit'
  end
end

But thanks to the accepts_nested_attributes_for in the ParentObject, the nested instances will be created as well.

I didn't include all the model and controller code in this response. You can see the rest of the code by downloading source code for this episode from github.


You can take a look at this answer I gave to a similar question. There're two options: with separate forms, or with a single form.

You'll just have to change the moderate_names_path to the correct path to your parent model instance (and of course the set of fields you want to modify). You can do it with polymorphic_path:

polymorphic_path([@parent_object, @child_object])
0

精彩评论

暂无评论...
验证码 换一张
取 消