8

我在使用 Rails 和 ActiveRecord 中的 mysql 位时遇到问题。我们为 Localities 的已发布状态存储了一些信息。

`published` bit(1) NOT NULL

我把它架published:binary在铁轨上。

Locality.first.published返回"\x01"

如何让 rails 将此字段视为布尔值?

有一张陈旧的票,但破解 ActiveRecord 并不是一个真正的选择。 https://rails.lighthouseapp.com/projects/8994/tickets/6102-activerecord-boolean-support-with-bit1-mysql-data-type

4

4 回答 4

6

您可以覆盖已发布属性的属性阅读器:

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

更新

或者为您的布尔返回值生成一个方法

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

所以你可以打电话:

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

但我认为第一个解决方案(覆盖属性读取器)更好。

于 2013-05-07T10:14:02.297 回答
3

Rails 5 的更新:新的属性 API 是为处理这种情况而设计的。首先,您定义一个ActiveRecord::Type::Value 处理deserialize从位到布尔,以及cast从布尔到位的子类:

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

然后使用帮助器在模型上定义属性attribute

class MyModel < ApplicationRecord
  attribute :published, Values::BitBoolean.new
end
于 2017-11-29T11:35:55.697 回答
1

感谢您的帮助@Mattherick。

在您的帮助下,我构建了一些更简单的东西:

  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

是存储在数据库highlight中的字段的名称。BIT此解决方案也适用checkbox于视图,无需更改:

  <div class="field">
    <%= f.label :highlight %>
    <%= f.check_box :highlight %>
  </div>
于 2017-04-26T19:15:08.617 回答
1

下面是基于@Mattherick 上述答案的扩展方法:

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)

并在初始化程序中要求:

config/initializers/extensions.rb

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

然后可以使用:

class Locality < ActiveRecord::Base
  alias_bit_to_boolean :published
end

这将产生一个locality.published?方法。

于 2016-10-18T21:06:54.577 回答