2010-02-08 45 views
6

我有一個存儲在MySQL表中BINARY(16)字段中的UUID的模型。我希望能夠透明地將十六進制uuid轉換爲setter方法的二進制文件,並在使用getter方法時將其轉換回來。如何透明地修改模型中的ActiveRecord方法?

什麼是「正確」的方式?

+0

下面的答案和評論有幫助嗎?你找到了適合你的東西嗎? – 2010-02-24 15:50:40

回答

7

您覆蓋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 

當然,你想要的二進制列的,因爲你發送的原始字節到數據庫。像這樣的遷移:

class AddUuidToUsers 
    def self.up 
    execute "ALTER TABLE users ADD uuid BINARY(16)" 
    end 
end 
+0

以每個模型或每個字段爲基礎重寫getter和setter並不像教ActiveRecord一般如何處理BINARY(16)那樣優雅。 – 2010-02-09 04:31:11

+2

使用add_column with:binary不提供BINARY類型。它會給出一個BLOB類型。 – 2010-02-09 04:31:44

+0

我也試過了上面的代碼示例,並遇到了一些問題。首先,我認爲你的意思是包裝(「C *」)而不是包裝(C *)。但更一般的說,如果可能的話,我會讓MySQL處理與BINARY(16)類型的轉換,而不是在Ruby中進行轉換。根據Aaron Scrugs在http://code.openark.org/blog/mysql/common-data-types-errors-compilation上的評論(#11),「HEX()和UNHEX()函數允許你在二進制數據和適用於應用程序的十六進制字符串。「 – 2010-02-09 04:41:34

1

我看了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 } 
} 

還要注意的是:二進制是不是你想要的,因爲這將創建一個BLOB列。

如果您有興趣,我建議擴展ActiveRecord以支持BINARY(16)類型。

更新:Matthew Higgins在以下博客文章搜索後似乎很有前途(「雖然可以在遷移中執行任意SQL語句,但另一種方法是擴展MySql適配器以支持新類型的列。」): http://www.strictlyuntyped.com/2008/07/mysql-lovin-part-2-adding-new-column.html

如果你得到這個工作,我希望你分享你的想法。像馬修一樣,我希望ActiveRecord有一個更清潔的API來添加列類型。