2010-02-08 10 views
6

Tengo un modelo con UUID almacenados en el campo BINARIO (16) en una tabla MySQL. Me gustaría poder convertir de forma transparente uuid hexadecimal en binario para el método setter y viceversa cuando uso el método getter.¿Cómo puedo modificar de forma transparente un método ActiveRecord en un modelo?

¿cuál es la forma "correcta" de proceder?

+0

¿Respondieron las respuestas y los comentarios a continuación? ¿Encontraste algo que funcionó para ti? –

Respuesta

7

anular el setter y 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 

Por supuesto, te gustaría una columna binaria, porque va a enviar bytes primas a la DB. Una migración como esta:

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

Reemplazar el getter y el setter por modelo o por campo no es tan elegante como enseñarle a ActiveRecord a manejar BINARY (16) en general. –

+2

Usar add_column con: binary no da un tipo BINARY. Le dará un tipo BLOB. –

+0

También probé los ejemplos de código anteriores y encontré algunos problemas. Primero, creo que quisiste decir paquete ("C *") en lugar de paquete (C *). Pero en términos más generales, si es posible, permitiría que MySQL maneje la conversión hacia y desde el tipo BINARY (16) en lugar de hacerlo en Ruby. De acuerdo con el comentario de Aaron Scrugs (# 11) en http://code.openark.org/blog/mysql/common-data-types-errors-compilation, "Las funciones HEX() y UNHEX() te permiten convertir entre datos binarios y la cadena hexadecimal amigable para la aplicación ". –

1

Miré el código fuente de ActiveRecord 2.3.5 (mysql_adapter.rb). En cuanto a la picadillo NATIVE_DATABASE_TYPES deja claro que no es compatible con el binario (16) tipo de datos:

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 } 
} 

También tenga en cuenta que: binario no es lo que quiere, porque eso crea una columna BLOB.

Si tiene la inclinación, le recomendaría extender ActiveRecord para que admita el tipo BINARY (16).

Actualización: después de algunas búsquedas, la siguiente publicación de Matthew Higgins parece prometedora ("Si bien las sentencias SQL arbitrarias se pueden ejecutar en migraciones, una alternativa es extender el adaptador MySql para admitir nuevos tipos de columnas"): http://www.strictlyuntyped.com/2008/07/mysql-lovin-part-2-adding-new-column.html

Si hace que esto funcione, espero que comparta lo que se le ocurra. Al igual que Matthew, me gustaría ver que ActiveRecord tenga una API más limpia para agregar tipos de columnas.

Cuestiones relacionadas