Rails / ActiveRecord working with mysql BIT

rails enum on model
rails generate model references
enumerations rails
rails enum labels
rails attr_accessor enum
rails 3.2 enum
rails timestamps
rails global enum

I'm having problems working with a mysql bit in Rails and ActiveRecord. We store a bit for the published-state of Localities.

`published` bit(1) NOT NULL

I scaffolded it as published:binary in rails.

Locality.first.publishedreturns "\x01".

How do I get rails to treat this field as a boolean?

There is a staled Ticket but hacking ActiveRecord is not really an option. https://rails.lighthouseapp.com/projects/8994/tickets/6102-activerecord-boolean-support-with-bit1-mysql-data-type

You can overwrite the attribute reader of your published attribute:

class Locality < ActiveRecord::Base
  # overwrite the attribute reader of the published attribute
  def published
    self.read_attribute(:published) == "\x01" ? true : false 
  end
end

UPDATE

Or generate a method for your boolean return value

class Locality < ActiveRecord::Base
  def to_boolean
    self.published == "\x01" ? true : false
  end
end

So you can call:

 Locality.first.published.to_boolean => true || false

But I think the first solution (overwriting attribute reader) is better.

fixtures with mysql bit(1) columns fail to load · Issue #18172 · rails , GitHub is home to over 40 million developers working together to host binary data in MySQL, and Binary in Active Record is represented as a  MySQL and PostgreSQL. Running the following commands will work as expected: bundle exec rails db:migrate bundle exec rails db:rollback We will get a column on the database that will only accept the declared values. That's the same constraint we have on our Rails app, yay!

Thank you for your help @Mattherick.

With your help I have built something easier:

  def highlight
    self.read_attribute(:highlight) == "\x01" ? true : false
  end

  def highlight=(value)
    content_value = (value == false || value == 0 || value == "0") ? "\x00" : "\x01"
    self.write_attribute(:highlight,content_value)
  end

The highlight is the name of the field stored as BIT on database. And this solution also works with checkbox on view without the need of changes:

  <div class="field">
    <%= f.label :highlight %>
    <%= f.check_box :highlight %>
  </div>

ActiveRecord Mysql2 incorrectly casting boolean values · Issue , MysqlAdapter and Mysql2Adapter are inconsistent in this respect. As mysql does not have a dedicated boolean type it's either 0 / 1 (tinyint) or t / f (  Learn more about how to use different primary key in rails with mysql.

Update for Rails 5: the new attributes API is made for handling situations just like this. First you define a subclass of ActiveRecord::Type::Value that handles deserializeing from bit to boolean, and casting back from boolean to bit:

module Values
  class BitBoolean < ActiveRecord::Type::Value
    BIT_FALSE = "\x00"
    BIT_TRUE = "\x01"

    def cast(value)
      value ? BIT_TRUE : BIT_FALSE
    end

    def deserialize(value)
      value == BIT_TRUE
    end
  end
end

Then you define the attribute on your model with the attribute helper:

class MyModel < ApplicationRecord
  attribute :published, Values::BitBoolean.new
end

Enums with Rails & ActiveRecord: an improved way, ActiveRecord Enums are a really good tool to use when you need that certain model's bundle exec rails g migration AddStatusToPosts We are using MySQL's enum() type to declare the possible values that the status column should have. Running the following commands will work as expected: Active Record is the ORM layer supplied with Rails. Active Record relieves us of the hassles of dealing with the underlying database, leaving us free to work on business logic. ActiveRecord relies on convention over configuration. Wherever possible, ActiveRecord guesses the correct configuration by reflecting against the data schema.

Heres an extension method based on @Mattherick's answer above:

lib/extensions/active_record/bit_boolean.rb

module Extensions::ActiveRecord
  module BitBoolean
    extend ActiveSupport::Concern

    class_methods do
      def alias_bit_to_boolean(attribute)
        define_method("#{attribute}?") do
          self.send(attribute) == "\x01" ? true : false
        end
      end
    end

  end
end

ActiveRecord::Base.send(:include, Extensions::ActiveRecord::BitBoolean)

and require in an initializer:

config/initializers/extensions.rb

require File.join(Rails.root, 'lib/extensions/active_record/bit_boolean.rb')

Which then can be used:

class Locality < ActiveRecord::Base
  alias_bit_to_boolean :published
end

This will produce a locality.published? method.

#6102 ActiveRecord: boolean support with bit(1) MySQL data type , BIT MySQL data type was added in MySQL 5.0.3 for MyISAM, and extended in 5.0.5 ruby: 1.8.7 gem mysql: 2.8.1 mysql server: 5.0.41. Problem. Activerecord#​column_name? return false instead of true when using datatype  Hi, Using mysql2 gem and activerecord, some queries fail. I may have troubles with my MySQL (misencoded values, double utf-8 encode, etc) but I don&#39;t know where is the problem. Here is the stac

Migrations, Active Record will work out which migrations should be run. t.boolean :​receive_newsletter , :default => false If the database does not support this (for example MySQL) then when a migration fails the parts of it that succeeded will not be  Active Record – Object-relational mapping in Rails ¶ ↑ Active Record connects classes to relational database tables to establish an almost zero-configuration persistence layer for applications. The library provides a base class that, when subclassed, sets up a mapping between the new class and an existing table in the database.

Configuring Rails Applications, By default, Rails assumes that primary key columns are are multiple developers working on the same application. config.active_record.​maintain_test_schema is a boolean value which controls whether Active Record will consider all tinyint(1) columns in a MySQL database to  ActiveRecord is the ORM that comes out-of-the-box with Rails. ActiveRecord (or AR) attempts to follow the Active Record design pattern . It plays the role of Model in the MVC architecture employed

Rails ActiveRecord with Database Column Defaults, I commonly set a default on my boolean columns when I'm defining a new migration. I do this primarily to minimize the potential for three states—  Pro Active Record helps you take advantage of the full power of your database engine from within your Ruby programs and Rails applications. ActiveRecord, part of the magic that makes the Rails framework so powerful and easy to use, is the model element of Rails model/view/controller framework.

Comments
  • I have already thought about doing it that way, but it does not seem like a good solution.
  • and why not? why are you not using a normal boolean field instead of the bit?
  • I would have used a boolean instead of a bit but I think it would break some legacy applications that are still in use. I just hoped to find a way around the comparison with "\x01" which could break sometime in the future.
  • well I understand. If you only want to work around the "\x01" I think the easiest way is to overwrite the attribute reader. Otherwise you´ll maybe have to change a lot of code overall your application, if the "\x01" will change to a normal boolean sometimes..