问题
I am appending some text to a notes
field on one of my ActiveRecord::Base
models but when I save it, it doesn't get updated:
valve.notes
#=> "Level: Top"
valve.notes << "\nDirection: North"
valve.notes
#=> "Level: Top\nDirection: North"
valve.save
#=> true
valve.reload.notes
#=> "Level: Top"
回答1:
Concat doesn't tell ActiveRecord that an Attribute has changed.
Figured it out and wanted to share it here for others (and most likely myself!) in the future.
I didn't know this but ActiveRecord cannot determine that an attribute has been changed (i.e. is dirty) when you concatenate it, either with concat()
or <<
. And because ActiveRecord only saves, or updates, attributes that have changed (i.e. are dirty), it doesn't update that attribute.
It's a sneaky little gotcha if you're not already aware of it because it not only fails silently, it doesn't think it's failed at all (and perhaps it hasn't, if you ask the ActiveRecord authors :).
valve.notes
#=> "Level: Top"
valve.notes << "\nDirection: North"
valve.changed?
#=> false
valve.notes_changed?
#=> false
valve.save
#=> true
valve.reload.notes
#=> "Level: Top"
You can read more about this on Rails' API Docs.
Solution
To get around this you need to do one of two things:
Let ActiveRecord know that the
notes
attribute has changed (i.e. it is now dirty):valve.notes << "\nDirection: North" valve.changed? #=> false valve.notes_will_change! valve.changed? #=> true
Don't use
concat()
or<<
to append to your attributes:valve.notes = "#{valve.notes}\nDirection: North" valve.changed? #=> true
Hope that helps at least one other soul.
JP
来源:https://stackoverflow.com/questions/29958538/rails-is-not-saving-an-attribute-that-is-changed