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)
我的 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:
完全覆盖 setterdef 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)