Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ActiveRecord not saving after updating attribute

I'm wondering if there is something at work here that I don't understand or if I've run into a bug in ActiveRecord (4.1.1).

I have a database full of records with only one attribute, a field a bit of JSON in it. I take one and try to update it like so.

test = Submission.find(1)
test.update_attribute('json_data',similar_but_different_json(test.json_data))

Let's assume the method similar_but_different_json makes a small update to that JSON. In my case I'm fixing some data errors that were created by a broken form.

When doing this, I don't get any errors, I show a commit in the console but no data submitted and get a return of true.

In order to actually update the record I have to do this.

test = Submission.find(1)
old_json_data = test.json_data
test.json_data = ""
test.json_data = similar_but_different_json(old_json_data)
test.save

What seems to be happening is that ActiveRecord doesn't identify that a change has been made that has to be saved. Could this be why setting the field to an empty string then back to JSON allows the record to save?

like image 959
rb- Avatar asked Dec 06 '22 02:12

rb-


2 Answers

will_change!

You can also use:

test.json_data_will_change!   # Goes before the save.

This will tell ActiveModel that the attribute, json_data, has changed (i.e. it's dirty ← there's a joke there somewhere) and will update the value properly on save.

See Rails is not saving an attribute that is changed for some more details as well.

like image 191
Joshua Pinter Avatar answered Dec 16 '22 23:12

Joshua Pinter


I don't understand why exactly the object is not marked dirty. A workaround is to use update_columns:

test.update_columns(json_data: similar_but_different_json(test.json_data))

It will execute an UPDATE query directly in the DB, without any validation, dirty check, etc... The json_data field must not be read-only though.

like image 33
Baldrick Avatar answered Dec 17 '22 00:12

Baldrick