Assuming you have a Postgres table called maps
, created by the following migration:
create_table :maps do |t|
t.string :name
t.string :grid, array: true, length: 3, default: Array.new(3,nil)
end
And you have the following ActiveRecord class with a function that modifies the grid
class Map < ActiveRecord
def update_grid(index, value)
grid[index] = value
g.save
end
end
This is what happens in the console:
m = Map.create
m.update_grid(0, "Foo")
m.reload.grid # => [nil,nil,nil]
So whats going on here? It turns out that ActiveRecord treats the array the same even though its contents have changed and hence ignores the changed values inside it. This happens when using in place or destructive changes like <<
, pop
or push
. To persist such a change in AR one needs to use the <attribute>_will_change!
method on an AR object which makes the attribute 'dirty'.
class Map < ActiveRecord
def update_grid(index, value)
grid_will_change!
grid[index] = value
g.save
end
end
and from the console you get this:
m = Map.create
m.update_grid(0, "Foo")
m.reload.grid # => ["Foo",nil,nil]