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.published
returns "\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.
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 deserialize
ing from bit to boolean, and cast
ing 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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With