views:

681

answers:

10

I'm trying to update one of my objects in my rails app and the changes just don't stick. There are no errors, and stepping through with the debugger just reveals that it thinks everything is updating.

Anyway, here is the code in question...

  qm = QuestionMembership.find(:first, :conditions => ["question_id = ? AND form_id = ?", q_id, form_id])
  qm.position = x
  qm.save

For reference sake, QuestionMembership has question_id, form_id, and position fields. All are integers, and have no db constraints.

That is basically my join table between Forms and Questions.

Stepping through the code, qm gets a valid object, the position of the object does get changed to the value of x, and save returns 'true'.

However, after the method exits, the object in the db is unchanged.

What am I missing?

A: 

Try changing qm.save to qm.save! and see if you get an exception message.

Edit: What happens when you watch the log on the call to .save!? Does it generate the expected SQL?

Tim Sullivan
Same result. I'm confused, to say the least.
CJ
I'm Thomas, nice to meet you, Confused! ;)
Thomas
What happens when you watch the log on the call to .save!? Does it generate the expected SQL?
Tim Sullivan
A: 

What is the result of qm.save? True or false? And what about qm.errors, does that provide anything that makes sense to you? And what does the development.log say?

August Lilleaas
A: 

You may not be finding the object that you think you are. Some experimenting in irb might be enlightening.

Also, as a general rule when changing only one attribute, it's better to write

qm.update_attribute(:position, x)

instead of setting and saving. Rails will then update only that column instead of the entire row. And you also get the benefit of the data being scrubbed.

A: 

I have run into this problem rather frequently. (I was about to say consistently, but I cannot, as that would imply that I would know when it was about to happen.)

While I have no solution to the underlying issue, I have found that it seems to happen to me only when I am trying to update mysql text fields. My workaround has been to set the field to do something like:

qm.position = ""
qm.save
qm.position = x
qm.save

And to answer everyone else... when I run qm.save! I get no errors. I have not tried qm.save?

When I run through my code in the rails console everything works perfectly as evidenced by re-finding the object using the same query brings the expected results.

I have the same issue when using qm.update_attribute(... as well

My workaround has gotten me limping this far, but hopefully someone on this thread will be able to help.

salt.racer
+1  A: 

Is there an after_save?

Is the correct SQL being emitted?

wombleton
Wrong SQL is coming out. What it does churn out is:UPDATE "question_memberships" SET "position" = 3, "updated_at" = '2009-03-17 19:09:44' WHERE "id" = NULLSince this is a join table, there is no "id" field. Back to the drawing board. I thought join tables didn't like id fields.
CJ
I would suspect that rails does not know that it shouldn't expect an id. I'd double check the has_many, belongs_to, et cetera instructions in the Question, Membership, and QuestionMembership classes.
wombleton
Check this http://stackoverflow.com/questions/522408/how-to-manage-table-without-id-in-rails out: it may be that you're after has_and_belongs_to_many instead of the more "modern" join-as-full-object.
wombleton
+1  A: 

In development log, you can actually see the sql that is generated.

For something like this:

qm = QuestionMembership.find(:first, :conditions => ["question_id = ? AND form_id = ?", q_id, form_id])
qm.position = x
qm.save

You should see something to the effect of:

SELECT * FROM question_memberships WHERE question_id=2 AND form_id=6 LIMIT 1
UPDATE question_memberships SET position = x WHERE id = 5

Can you output what sql you are actually seeing so we can compare?

XGamerX
A: 

Use ./script/console and run this script.. step by step..

see if the position field for the object is update or not when you run line 2

then hit qm.save or qm.save!... to test

see what happens. Also as mentioned by Tim .. check the logs

Rishav Rastogi
A: 

Check your QuestionMembership class and verify that position does not have something like

 attr_readonly :position

Best way to debug this is to do

 tail -f log/development.log

And then open another console and do the code executing the save statement. Verify that the actual SQL Update statement is executed.

ucron
A: 

Check to make sure your database settings are correct. If you're working with multiple databases (or haven't changed the default sqlite3 database to MySQL) you may be working with the wrong database.

Run the commands in ./script/console to see if you see the same behavior.

Verify that a similar object (say a Form or Question) saves.

If the Form or Question saves, find the difference between the QuestionMembership and Form or Question object.

Steropes
A: 

Turns out that it was emitting the wrong SQL. Basically it was looking for the QuestionMembeship object by the id column which doesn't exist.

I was under the impression that that column was unnecessary with has_many_through relationships, although it seems I was misguided.

To fix, I simply added the id column to the table as a primary key. Thanks for all the pointers.

CJ