tinyint(1) and boolean

58 views
Skip to first unread message

codeinnova

unread,
Jan 9, 2010, 6:16:41 PM1/9/10
to Ruby on Rails: Talk
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.

Frederick Cheung

unread,
Jan 10, 2010, 2:11:20 AM1/10/10
to Ruby on Rails: Talk
On Jan 9, 11:16 pm, codeinnova <sumangur...@gmail.com> wrote:
> 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?

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

Matt Jones

unread,
Jan 10, 2010, 2:57:15 PM1/10/10
to Ruby on Rails: Talk

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? :)

--Matt Jones

Jeff Lewis

unread,
Jan 11, 2010, 1:58:44 PM1/11/10
to Ruby on Rails: Talk
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

Matt Jones

unread,
May 21, 2015, 10:42:57 AM5/21/15
to rubyonra...@googlegroups.com


On Sunday, 10 January 2010 14:57:15 UTC-5, Matt Jones wrote:

On Jan 9, 6:16 pm, codeinnova <sumangur...@gmail.com> wrote:
> 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?

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...

 
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.


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
Reply all
Reply to author
Forward
0 new messages