Reputation: 75
Weirdness:
I'm working in rails 4.1 with a postgres backend. One of my models has some array fields, which I'm hoping are properly handled by the 'pg' gem (0.17.1). My migration file and the resulting schema can be found below.
The field in question is a string array. Below, I've posted the migration, the resulting schema, and the code that doesn't seem to be working (along with 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: '{}'
schema:
t.string "test", default: [], array: true
Here are the steps I'm using to to reproduce this in the rails console (assuming a basic user model has been 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 properly -- it has an empty array set for that field -- and I can do array operations on it. But somehow I can't get any modifications to stick.
FYI, I am able to modify and save other fields using the same procedure; it's just the arrays that are behaving like this.
Any ideas?
Edit:
u.test.push('newitem')returns the new array as I would expect. No sign of anything going wrong, or some error with validates_uniqueness_of -- would I see that firing in the console? Thanks to the first comment, I've now tested using 'update':
u.update(test: [(u.test << 'testValue')].flatten)
gives me the behavior I want, but it seems really clumsy. Is there something I need to change in the model? I'm not sure how what I'm doing makes validates_uniqueness_of fire (it's not set in the model).
Upvotes: 4
Views: 908
Reputation: 2488
There is (at least it used to be) a problem with using ruby array operators like push
or <<
on ActiveRecord fields. They are not marked as dirty and are not updated in the database on save
. Try this:
u = User.first()
u.test_will_change!
u.test.push('testValue')
u.save
User.find(1).test
attribute_will_change!
marks attribute as dirty, making sure that it will be serialized and saved into the database on save
.
Upvotes: 6