Has_many: inserting children when inserting parent


#1

disclaimer: am in the midst of my first ruby/rails project

I have a situation where I want several child records to be created when
a new parent record is created. The following represents my first stab
at coding it, am I on the right track?

Here is the model:

parents

id
name

children

id
parent_id
name

class Parent < ActiveRecord::Base
has_many: children
end

class Child < ActiveRecord::Base
belongs_to: child
end

the rhtml form has two text fields, one for a parent’s name and one for
a space delimited list of childrens’ names.

<%= text_field ‘parent’, ‘name’ %>
<%= text_field ‘childlist’, ‘names’ %>

Now the ParentController and its create method which I would like to
save both the parent and all its childeren:

class ParentsController < ApplicationController
def create
@parent = Parent.new(params[:parent])
@parent.save

childnames = params[:childlist][:names]
childname.split(/\s+/).each do |name|
  child = Child.new({ :parent_id => @parent.id, :name => name})
  child.save
  @parent.children << child
end

redirect_to :action => 'list'

end

Is this the right approach? Are there any ruby-isms or rails-ims I am
not picking up on?


#2

Basically it’s all good, however, you can place the call to @parent.save
after adding all the children, the advantage of this is than error
thrown before save will not result in a lonely parent. Also I think
Rails wraps the statements in a transaction if you do this, meaning that
nothing will be saved if anything goes wrong. Also, the child.save is
unneccessary in this case. (Oh and so is the local variable, and passing
parent_id :slight_smile:

Like this:

class ParentsController < ApplicationController
def create
@parent = Parent.new(params[:parent])

 params[:childlist][:names].split(/\s+/).each do |name|
   @parent.children << Child.new({ :name => name })
 end

 @parent.save

 redirect_to :action => 'list'

end


#3

sorry, code should have read:

def update
@parent = Parent.find(params[:id])
@parent.children.each { |child| child.destroy }

params[:childlist][:names].split(/\s+/).each do |name|
@parent.children << Child.new({ :name => name })
end

if @parent.update_attributes(params[:parent])
redirect_to :action => ‘list’
else
render :action => ‘edit’
end
end


#4

Wow thanks, I’m liking rails more and more. The behind the scene stuff
tho like setting the parent id automatically and saving the newly
children automatically is going to take some getting used to.

Now I have a question with my update method. I’ll need to delete the
existing children and add in the new children (assume a form similar to
the one for a new parent with one text field for the children).

The following works fine, but I’m wondering, is there more auto-magic I
am not taking advantage of?

def update
@parent = Parent.find(params[:id])
@parent.children.each { |child| child.destroy }

params[:childlist][:names].split(/\s+/).each do |name|
@parent.children << Child.new({ :name => name })
end

if @challenge.update_attributes(params[:challenge])
redirect_to :action => ‘list’
else
render :action => ‘edit’
end
end