Rails - Boolean field not saved on PostgreSQL / Heroku
-
10-02-2021 - |
Question
Got a strange problem:
Boolean field not getting saved on Heroku (works fine locally)
Details:
Rails 2.3 on Heroku (bamboo-ree-1.8.7).
Migration
def self.up
add_column :users, :send_contact_emails, :boolean, :default => false
end
On Heroku:
>> u = User.last
=> #<User id: 100, ......
>> u.send_contact_emails = true
=> true
>> u.save
=> true
>> x = User.last
=> #<User id: 100, ...
>> x.send_contact_emails
=> nil <---------------------------- Why is this ?
When I do this locally (Postgresql 8.4), it works as expected.
Any ideas ?
EDIT:
Ran some tests directly on the DB:
>> ActiveRecord::Base.connection.execute("SELECT send_contact_emails from users where id = 100")[0]
=> {"send_contact_emails"=>nil}
>> ActiveRecord::Base.connection.execute("UPDATE users SET send_contact_emails=FALSE where id=100")
=> #<PGresult:0x7f76d7593580>
>> ActiveRecord::Base.connection.execute("SELECT send_contact_emails from users where id = 100")[0]
=> {"send_contact_emails"=>"f"}
So the problem is with Rails and not Postgresql...
Solution 2
Looks like the problem was on the RAILS side.
Once I manually updated the values to false:
ActiveRecord::Base.connection.execute("UPDATE users SET send_contact_emails=FALSE")
The problem disappeared.
(As if rails 2.3.10 was unable to handle 'nil' in boolean fields..)
OTHER TIPS
Make sure that you restart your app.
http://devcenter.heroku.com/articles/rake
Once you run migrations that add new columns, you have to manually restart your app on heroku with "heroku restart" so that Rails will pick up the changes.
Boolean in Rails uses tinyint column type, so it's 1/0 on DB level side.
API
Class
ActiveRecord::ConnectionAdapters::MysqlAdapter < AbstractAdapter
emulate_booleans
By default, the MysqlAdapter will consider all columns of type tinyint(1) as boolean. If you wish to disable this emulation (which was the default behavior in versions 0.13.1 and earlier) you can add the following line to your environment.rb file:
ActiveRecord::ConnectionAdapters::MysqlAdapter.emulate_booleans = false