Save new model with child model


#1

Hi,

I am having a problem saving a new model that has an associated child
model. If a new ticket is being created and will have one comment to
go with it then I tried this in my action

  @ticket = Ticket.new(params[:ticket])
  @comment = Comment.new(params[:comment])
  @ticket.comments << @comment
  if @ticket.save
      @notice = "Ticket added. Thanks for contributing!"
      @ticket = Ticket.new
      @comment = Comment.new
  else
    @notice = "Sorry, unable to add ticket."
  end

The save always fails because the comment does not have a ticket_id
specified. How can I specify the ticket_id for the comment if the
ticket id doesn’t even exist before I call save. I thought Rails would
take care of this for me when I use the << or push(). (Rails 1.0)

Any ideas what to do?

Thanks,
Peter


#2

On 4/25/06, Peter M. removed_email_address@domain.invalid wrote:

Hi,

I am having a problem saving a new model that has an associated child
model. If a new ticket is being created and will have one comment to
go with it then I tried this in my action

[snip]

I am current going to all this effort which just seems wrong.

  @ticket = Ticket.new(params[:ticket])
  @comment = Comment.new(params[:comment])

  if @ticket.save
    @comment.ticket_id = @ticket.id
    @ticket.comments << @comment
    if @comment.save
      @notice = "Ticket added"
    else
      @ticket.destroy
      @notice = "Sorry, unable to add ticket."
    end
  else
    @notice = "Sorry, unable to add ticket."
  end

There must be a simpler way. Any ideas?

Thanks,
Peter


#3

Hi Jeremy,

Thanks for the code. Unfortunately it didn’t work:S The save still
results in an error because the ticket_id is not set for the comment.
What to do?

Thanks
Peter

On 27 Apr 2006 14:14:52 -0000, Jeremy M.


#4

You almost have it. Try:

def new
@ticket = Ticket.new
@comment = Comment.new
render :action => ‘new’
end

def create
@ticket = Ticket.new(params[:ticket])
@comment = Comment.new(params[:comment])
@comment.ticket = @ticket

if @comment.save
  flash[:notice] = "Ticket added. Thanks for contributing!"
  redirect_to :action => 'new'
else
  flash[:notice] = "Sorry, unable to add ticket."
  render :action => 'new'
end

end


#5

Hi,

Please tell me there is something simpler.

Peter


#6

Is the comment attached with a through relationship, or a straight
has_many?

the << does not work with through relations.

Otherwise with a normal has_many,

@ticket = Ticket.new(params[:ticket])
@ticket.comments << Comment.new(params[:comment])
@ticket.save!

should set the foreign keys automatically in the Comment object as I
understand it.

Could you post the relevant lines of your Ticket model?


#7

I’m at work at the moment, I’ll look at it when I get home…

Just one more thought though.

Have you tried

@ticket.comments.create( Comment.new(params[:comment])

This may work… Failing this I will try it when I get home


#8

Hi Liquid,

On 4/30/06, Liquid removed_email_address@domain.invalid wrote:

Is the comment attached with a through relationship, or a straight has_many?

the has_many is just a regular relationship

Could you post the relevant lines of your Ticket model?
class Ticket < ActiveRecord::Base
has_many :comments, :dependent=>:delete_all
end

Any ideas why it might not work? I doubt this is a bug in Rails but I
don’t seem to be doing anything obviously wrong.

Thanks,
Peter


#9

Hi Liquid,

Thank you for the investigation. Wow!

In my table definitions I have something like

id INT NOT NULL

I will try changing this and let you know what happens. It seems like
this is probably the problem.

I really appreciate your help.

Peter


#10

Hi Peter,

I had tried some test code without any problems. I have included the
code
below for the example that I used.

Can you post your table definitions?

Table Defs:
tickets
id INT
title STRING

comments
id INT
description STRING
ticket_id INT

Ticket Model:

class Ticket < ActiveRecord::Base
has_many :comments, :dependent => :delete_all
end

Comment Model:

class Comment < ActiveRecord::Base
belongs_to :ticket
end

Ticket Controller:

class TicketController < ApplicationController

def list
@tickets = Ticket.find(:all)
end

def new
if request.post?
@ticket = Ticket.new(params[:ticket])
@ticket.comments << Comment.new(params[:comment])
if @ticket.save
flash[:notice] = “Saved”
redirect_to :action => :list
else
flash[:notice] = “Not Saved”
end
else
@ticket = Ticket.new
end
end

end

Ticket View - New

<%= start_form_tag :action => :new %>
Ticket Title: <%= text_field “ticket”, “title” %>


Comment: <%= text_field “comment”, “description” %>


<%= submit_tag %>
<%= end_form_tag %>


#11

I don’t think that will help you.

The table defs that I used I did not completely specify in the post.

The ID column is NOT NULL that I used in both tables. All I included in
the
post was the column name and type. Sorri for the inconvienience.