Has many / belongs to error with mysql

Hi,

I’ve got stuck with a problem on my rails app - I’ve created a database
for quotes and bookings, with a futher table “eventdetails” (details of
a quote or booking) linked one-one for both tables using a polymorphic
assciation. This all works, but I am now trying to link a quote to a
number of bookings with a has_many and belongs_to (the foreign key is in
the booking table). When I try and save a new booking with this link,
it all breaks… so I’m wondering if I’ve got something wring with the
way I’m doing it all!

I’ve drawn out all my tables and links, etc here:
http://www.markpaxton.net/stuff/rigs.jpg

I’d be most appreciative if anyone could take a look and help me to
figure out where the root of my problems are!

Cheers,
Mark

Can you post your controller code? Have you tried using the console to
do it by hand – I often find it’s a good way to walk through saving
problems, e.g. r = Rig.new; r.save; r.errors

Chris T wrote:

Can you post your controller code? Have you tried using the console to
do it by hand – I often find it’s a good way to walk through saving
problems, e.g. r = Rig.new; r.save; r.errors

Thanks for the help, I 'll post the controller code later when I get
back to the right computer. I have tried stepping through using the
console though with the same result, so I’m thinking it’s my general
approach that is at fault, which is:

@quote = Quote.find(7)
@new_eventdetails = @quote.eventdetails.clone
@new_rig_items = @eventdetails.rig_items.clone
@new_eventdetails.rig_items = @new_rig_items

@rig = Rig.new
@rig.eventdetails = @new_eventdetails
@rig.quote = @quote

@rig.save

Cheers,
Mark

Chris T wrote:

Can you post your controller code? Have you tried using the console to
do it by hand – I often find it’s a good way to walk through saving
problems, e.g. r = Rig.new; r.save; r.errors

I’ve posted the two methods (new/create) from my controller here:

http://www.markpaxton.net/stuff/rig_controller.txt

Cheers,
Mark

Mark P. wrote:

approach that is at fault, which is:
@rig.save

Cheers,
Mark

Mark
Finding it a bit difficult to get my head around this, but it would help
to know what output the console was giving after each statement. My
guess is that the eventdetails are being lost somewhere in the mix, but
it’s difficult to see where at the moment. Sorry I can’t be more help

Offtopic, but I was wondering what you used to make that diagram?
Thanks!

Guest wrote:

Offtopic, but I was wondering what you used to make that diagram?
Thanks!

Macromedia Fireworks :slight_smile: I wonder if there’s some clever app somewhere
that could let you graphically represent/create the associateion between
models.

Mark

On Jul 12, 2006, at 9:01 AM, Mark P. wrote:


Posted via http://www.ruby-forum.com/.


Rails mailing list
[email protected]
http://lists.rubyonrails.org/mailman/listinfo/rails

http://rav.rubyforge.org/ :wink:

Cheers-
-Ezra

Chris T wrote:

Mark P. wrote:

approach that is at fault, which is:
@rig.save

Cheers,
Mark

Mark
Finding it a bit difficult to get my head around this, but it would help
to know what output the console was giving after each statement. My
guess is that the eventdetails are being lost somewhere in the mix, but
it’s difficult to see where at the moment. Sorry I can’t be more help

Hi,

Thanks for the help again, I’ve uploaded a console log here:
http://www.markpaxton.net/stuff/console.txt

It’s a bit ugly but I’ve tried to format it slightly. It’s a slightly
different message I got before, but all to the same effect.

Mark

Mark

Looking at this, my guess is the problem is that @rig is a new record
which has a (1:1) associated record @eventdetail, which is also a new
record. This, I think, is the first problem. Rig has_one :eventdetail
(i.e. rig is a parent of eventdetail), and when you save a parent the
child isn’t automatically saved (although the converse is true).

The other problem would seem to be that the new eventdetail (which
belongs_to @rig) has_many :rig_items, which are also new records, and
which also won’t be automatically be saved when @rig is saved.

I’m wondered if the whole things is causing Active Record to behave
oddly, which is why you’ve ended up with that strange MySQL statement. I
think it might be worth considering how you’re coding this, as I’m not
sure you’ll be able to save all in one step (perhaps wrapping up in a
transaction) .

Perhaps if you made the association between @eventdetail and @rig, then
saved the @eventdetail (thus automatically saving the child @rig),
adding the :rig_items to @eventdetail and then adding the quote to @rig.
Sorry if that’s not entriely clear. My head is elsewhere at the moment.
:slight_smile:

I’ve done another bit of investigation. Having created a Rig without
the association in the models, I then restored the association and tried
to look at the rig using the console:
http://www.markpaxton.net/stuff/rig_load_console.txt

It all seems to go wrong when I try and load the eventdetil associated
with the Rig… it gets confused with the eventdetail associated with
the quote:

@rig.id => 2
@rig.quote.id => 8

@rig.quote.eventdetail does:
SELECT * FROM eventdetails WHERE (eventdetails.describable_id = 8 AND
eventdetails.describable_type = ‘Quote’

BUT

@rig.eventdetail does:
SELECT * FROM eventdetails WHERE (eventdetails.describable_id =
#Quote:0x3a78d00 AND eventdetails.describable_type = ‘Rig’

Where it should do:
SELECT * FROM eventdetails WHERE (eventdetails.describable_id = 2 AND
eventdetails.describable_type = ‘Rig’

So what’s going wrong is somehow the rig.eventdetail and
rig.quote.eventdetail are getting mixed up and the wrong id is used in
the query…

Mark

Hi,

I’m not entirely sure that’s the probem, as the code I’m using is the
same as the Quote code. It’s all very useful nontheless as it’s giving
more more information to trace the problem with. Here is the code from
the quote controller which works perfectly:
http://www.markpaxton.net/stuff/quote_controller.txt

Chris T wrote:

Rig has_one :eventdetail
(i.e. rig is a parent of eventdetail), and when you save a parent the
child isn’t automatically saved (although the converse is true).

The other problem would seem to be that the new eventdetail (which
belongs_to @rig) has_many :rig_items, which are also new records, and
which also won’t be automatically be saved when @rig is saved.

In my working quote controller, the child Rig_items are associated to
unsaved Eventdetail, then the unsaved Eventdetail is assigned to the
unsaved Quote. When the Quote is saved, the Eventdetail and Rig_items
are saved in one go, automatically transactioned by active record. You
can see this in my development log:
http://www.markpaxton.net/stuff/quote_create_log.txt

Comparing this with creating a rig and you can see all kinds of mess
going on:
http://www.markpaxton.net/stuff/rig_create_log.txt

The same code works as soon as you remove the association with Quote
from the Rig and Quote models, as per this log:
http://www.markpaxton.net/stuff/rig_create_success_log.txt

So from this info, it seems that for some reason active record is trying
to do something unexpected with the associated Quote when saving the
Rig.

What I’m expecting to happen is that when I do:
@rig.quote = @quote
nothing is saved. When I do:
@rig.save
then the association (@rig.quote_id) is saved, but not the quote (as
it’s an existing record).
I would have only expected problems if I’d done
@quote.rigs << @rig
Which would try and save the Rig straight away, as I’d have to validate
it first. In fact replacing @rig.quote = @quote with @quote.rigs <<
@rig still causes the same error and log messages.

So again I’m quite stuck, but the problem is narrowed down to exactly
what should happen / actually happens when you try and save a new record
with an existing record associated to it.

Cheers,
Mark

You’re right, that is strange. This is where one of the polymorphic
experts like Josh chimes in with a helpful suggestion… :slight_smile:

Correct me if I’m wrong, but isn’t @eventdetail on the Quote code an
existing record, whereas on the rig one it’s a new record?

Quick google turned up this:

I now have a working solution, though I changed the relationship I
wanted in the end as I figured out a better way:

I’ll post the gory details later by now I have polymorphic one to many
from eventdetails to rigs and quotes. Makes more sense that both quotes
and rigs can spawn more quotes and more rigs than just one quote going
to one rig.

Thanks for all the help… I’d still be really interested to know what
the problem with the original idea was!

Mark

class Eventdetail < ActiveRecord::Base
belongs_to :person
belongs_to :organisation
belongs_to :describable, :polymorphic => true
belongs_to :based_on, :polymorphic => true

class Rig < ActiveRecord::Base

has_one :eventdetail, :as => :describable
belongs_to :rigstatus
belongs_to :teccy
has_many :follow_on_details, :class_name => “Eventdetail”, :as =>
:based_on

class Quote < ActiveRecord::Base
has_one :eventdetail, :as => :describable
belongs_to :quotestatus
belongs_to :teccy
has_many :follow_on_details, :class_name => “Eventdetail”, :as =>
:based_on

Here’s my models and controller code now - it’s not quite fully checked,
but it seems to work.

http://www.markpaxton.net/stuff/models.txt
http://www.markpaxton.net/stuff/controllers.txt

Mark

Chris T wrote:

Correct me if I’m wrong, but isn’t @eventdetail on the Quote code an
existing record, whereas on the rig one it’s a new record?

No, the @eventdetail is a new record saved in the session for both Rig
and Quote, it’s not obvious to figure out unless you know that
find_eventdetail does this:

def find_eventdetail
session[:eventdetail] ||= Eventdetail.new
end

Similar to find_cart in the Agile book.

When creating a Rig from an existing Quote, @quote.eventdetail is cloned
and saved in the session too.

Mark