Rails 4.1 Postgres String Arrays: Can't save after change
Weirdness:
I am working in rails 4.1 with postgres support. One of my models has several array fields, which I hope are correctly handled by pearl "pg" (0.17.1). My migration file and resulting schema can be found below.
The field in question is a string array. Below I've posted the migration, the resulting schema, and code that doesn't seem to work (along with the output when this code is run in the rails console).
I don't have anything in the User model that references this field.
migration:
add_column :users, :test, :string, :array => true, default: '{}'
scheme:
t.string "test", default: [], array: true
Here are the steps I use to reproduce this in the rails console (assuming a base user model is created to hold the field):
u = User.first()
u.test.push('testValue')
u # => #<User id: 1, name: "dave", passhash: nil, email: nil, created_at: "2014-10-04 10:12:29", updated_at: "2014-10-04 10:12:29", provider: "identity", uid: "1", oauth_token: nil, oauth_expires_at: nil, test: ["testValue"]>
u.save
User.find(1).test # => []
So the user record seems to be initialized correctly - it has an empty array set for that field - and I can perform array operations. But somehow I can't get any changes.
FYI, I can modify and save other fields using the same procedure; they are just arrays that behave like this.
Any ideas?
Edit:
u.test.push ('newitem') returns a new array as I expected. No indication that something is wrong, or some error with validates_uniqueness_of - will I see that shooting in the console? Thanks to the first comment, I've now tested with 'update':
u.update(test: [(u.test << 'testValue')].flatten)
gives me the behavior I want, but it seems really awkward. Is there something I need to change in the model? I'm not sure if what I'm doing is validates_uniqueness_of fire (it's not set in the model).
source to share
There is (at least sometime) a problem with using ruby ββarray operators like push
or <<
in ActiveRecord fields. They are not marked dirty and are not updated in the database by save
. Try the following:
u = User.first()
u.test_will_change!
u.test.push('testValue')
u.save
User.find(1).test
attribute_will_change!
marks the attribute as dirty by making sure it gets serialized and stored in the database with save
.
source to share