Hieu Nguyen

ActiveRecord 3.2 bug: Can not save when mutate string attribute

Jan 17 2016

This is the English version of my original post.

Note: This bug is fixed from ActiveRecord 4.0

The weird bug

user = User.first # => #<User id: 1, email: "someone@email.com">
user.email.gsub!('email', 'mail')

User.first.email # => still "someone@email.com"

The cause

When you use save, Rails check to see whether the attributes are changed before update the record in database. To optimize that process, it used the reference instead of the value of the attributes. Therefore, when you mutate the attribute (using gsub! or something similar), the reference won’t change, and it won’t pass the check.

How to fix

Simply create another reference for the attribute:

user = User.first # => #<User id: 1, email: "someone@email.com">
user.email = user.email.gsub('email', 'mail')

User.first.email # => "someone@mail.com"

Lession learn

Mutation lead to a lot of side-effect bugs like this, so I try to avoid it whenever possible. It’s just so convenient in Rails, though…