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.

Fred

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.

Jeff

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: rails/attributes.rb at daffea59db118fce4247d335eabea026cc54d7bc · rails/rails · GitHub

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

end

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

–Matt Jones