【发布时间】:2010-02-08 19:10:02
【问题描述】:
我有一个模型,其 UUID 存储在 MySQL 表的 BINARY(16) 字段中。我希望能够透明地将十六进制 uuid 转换为 setter 方法的二进制,并在我使用 getter 方法时转换回来。
什么是“正确”的进行方式?
【问题讨论】:
-
下面的答案和 cmets 有帮助吗?你找到适合你的东西了吗?
标签: ruby-on-rails activerecord
我有一个模型,其 UUID 存储在 MySQL 表的 BINARY(16) 字段中。我希望能够透明地将十六进制 uuid 转换为 setter 方法的二进制,并在我使用 getter 方法时转换回来。
什么是“正确”的进行方式?
【问题讨论】:
标签: ruby-on-rails activerecord
你覆盖了 setter 和 getter:
class User < ActiveRecord::Base
def uuid=(value)
@uuid = write_attribute(:uuid, value.scan(/../).map {|n| n.to_i(16)}.pack("C*"))
end
def uuid
@uuid ||= read_attribute(:uuid).unpack("C*").map {|n| sprintf("%02x", n)}.join
end
end
当然,您需要一个 BINARY 列,因为您将原始字节发送到数据库。像这样的迁移:
class AddUuidToUsers
def self.up
execute "ALTER TABLE users ADD uuid BINARY(16)"
end
end
【讨论】:
我查看了 ActiveRecord 2.3.5 (mysql_adapter.rb) 的源代码。查看 NATIVE_DATABASE_TYPES 哈希可以清楚地表明它不支持 BINARY(16) 数据类型:
NATIVE_DATABASE_TYPES = {
:primary_key => "int(11) DEFAULT NULL auto_increment PRIMARY KEY".freeze,
:string => { :name => "varchar", :limit => 255 },
:text => { :name => "text" },
:integer => { :name => "int", :limit => 4 },
:float => { :name => "float" },
:decimal => { :name => "decimal" },
:datetime => { :name => "datetime" },
:timestamp => { :name => "datetime" },
:time => { :name => "time" },
:date => { :name => "date" },
:binary => { :name => "blob" },
:boolean => { :name => "tinyint", :limit => 1 }
}
还要注意 :binary 不是您想要的,因为这会创建一个 BLOB 列。
如果您愿意,我建议您扩展 ActiveRecord 以支持 BINARY(16) 类型。
更新:在 Matthew Higgins 的以下博客文章中进行了一些搜索后,似乎很有希望(“虽然可以在迁移中执行任意 SQL 语句,但另一种方法是扩展 MySql 适配器以支持新类型的列。”): http://www.strictlyuntyped.com/2008/07/mysql-lovin-part-2-adding-new-column.html
如果你能做到这一点,我希望你能分享你的想法。和 Matthew 一样,我希望 ActiveRecord 有一个更简洁的 API 来添加列类型。
【讨论】: