tinyint(1) and boolean

So i had a boolean attribute in my model which gets interpreted to
tinyint(1) in mysql by rails migrations. Now tinyint(1) accepts a
range in mysql and i want to change my boolean attribute to an
attribute which can accept 3 values(0,1,2).
I made the change to the view and when i post the form selecting the
selecting the value '2', it still gets saved as a '0'. I checked the
params when the post is done and the value of the form element was '0'
even though i selected '2'(I am using a dropdown list here).
So my question really is, how can i make rails to accept more values
without changing the type to something other than tinyint(1)? And why
this weirdness?

thanks in advance.

Mysql doesn't have an actual boolean type so rails usually uses tinyint
(1) columns instead. There is a setting inside the mysql_adapter
called emulate_booleans which you could try turning off but that would
apply to all tables.


As others have pointed out, MySQL doesn't have a straight "boolean"
field type, so the tinyint(1) hack is used instead.

You'll either need to turn off emulate_booleans (which may break other
stuff) or just change the column type, as the MySQL adapter will
detect the current type as :boolean and the AR-generated accessors
will wind up casting values as booleans automatically...

Not to mention the potential for confusion - imagine you're another
developer, looking at schema.rb. You see a field 'foo' declared
as :boolean, and the interface stuffs '2' in there - what's it
supposed to mean? FILE_NOT_FOUND? :slight_smile:

--Matt Jones

I second Matt's point about potential for confusion. A boolean val
implies one of two values: true or false. What you're asking for -- 1
of 3 potential vals -- seems to rule out the use of a boolean to
represent that val. So, I'd recommend using some other data type.


Updating this old post, because there’s now a way to handle situations where you’ve got a tinyint(1) column that has non-0/1 values in it.

The relevant documentation is here: https://github.com/rails/rails/blob/daffea59db118fce4247d335eabea026cc54d7bc/activerecord/lib/active_record/attributes.rb#L17

Note that in 4.2.1 the entire module is #:nodoc:, but it has been made public in master.

To use it, you redeclare a column that would otherwise be misdetected. Example:

class SomeModel < ActiveRecord::Base

attribute :a_tinyint_1_column_that_isnt_a_boolean, Type::Integer.new


Passing an instance of ActiveRecord::Type::Integer means the column will not have the boolean typecasting behavior anymore.

–Matt Jones