Rails 4.1 - 写入 MySQL 数据库而不进行类型转换

Rails 4.1 - Write to MySQL database without typecasting

我的 MySQL 数据库中有一列是 TINYINT(1) 类型。我需要在此列中存储实际整数。问题是,由于列类型,Rails 4.1 假设此列仅包含布尔值,因此它在写入数据库时​​将除 0 或 1 之外的所有值都类型转换为 0。

我不想简单地禁用布尔仿真,因为我们的数据库中有许多列,我们在其中使用 TINYINT(1) 来实际表示布尔值。我目前无法更改 MySQL.

中的列类型

如何强制 Rails 4.1 绕过类型转换步骤并直接写入数据库?


(摘自 Rails 4.1 源代码可能会有一些用处:https://github.com/rails/rails/blob/4-1-stable/activerecord/lib/active_record/attribute_methods/write.rb

我不知道它是否有效,但您可以尝试使用以下方法覆盖 setter:raw_write_attribute 或:write_attribute。 The :raw_write_attribute and :write_attribute methods disable/enable the type casting before writing.

假设 attribute/column 的名称为:the_boolean_column_who_wanted_to_be_an_integer,您可以这样做:

def the_boolean_column_who_wanted_to_be_an_integer=(value)
  raw_write_attribute(:the_boolean_column_who_wanted_to_be_an_integer, value) # or write_attribute(...
end

有效吗?

也许您应该使用 rails 4.1 source code:

完全覆盖 setter
def the_field=(value)
    attr_name = 'the_field'
    attr_name = self.class.primary_key if attr_name == 'id' && self.class.primary_key
    @attributes_cache.delete(attr_name)
    column = column_for_attribute(attr_name)

    # If we're dealing with a binary column, write the data to the cache
    # so we don't attempt to typecast multiple times.
    if column && column.binary?
      @attributes_cache[attr_name] = value
    end

    if column || @attributes.has_key?(attr_name)
      @attributes[attr_name] = value
    else
      raise ActiveModel::MissingAttributeError, "can't write unknown attribute `#{attr_name}'"
    end
end

请注意,@attributes[attr_name] = send(type_cast_method, column, value) 已更改为 @attributes[attr_name] = value。您可以针对您的用例简化它。另请注意,我还没有尝试过这个,即使它有效,你也应该在升级时小心 rails.

方案 A:更改为 SMALLINT(2 个字节)作为折衷方案。

B 计划:看看 TINYINT(3) 是否会愚弄 Rails 使其不认为它是布尔值。

C 计划:看看 TINYINT UNSIGNED 是否会愚弄 Rails 不认为它是布尔值。 (假设您的数字是非负数:0..255。)

你可以使用原始 SQL 来插入吗?

类似于:

sql = "INSERT INTO my_table (smallnumber) VALUES (100)"
ActiveRecord::Base.connection.execute(sql)