2011-01-22 9 views
12

Estoy escribiendo una secuencia de comandos de migración para crear una tabla con una columna de clave principal que se llama guid y es VARCHAR(25). El problema es que siento que tengo que duplicar mi esfuerzo para lograr lo que debería ser posible en un solo paso.Migración de carriles Crear clave principal de tabla

Si me quedo:

create_table(:global_feeds, :primary_key => 'guid') do |t| 
    t.string :guid, :limit => 25 
    t.text :title 
    t.text :subtitle 

    ... 

    t.timestamps 
end 

me sale una tabla con una clave principal llamado guid ninguna columna llamada id (que es lo que quiero). Sin embargo, el problema es que la columna guid es INT(11) con el incremento automático activado. Así que tengo que ejecutar un comando adicional:

change_column :global_feeds, :guid, :string, :limit => 25 

parece un poco complicado a tener que correr básicamente dos comandos SQL para obtener lo que creo que debería ser posible en uno.

¿Alguna sugerencia sobre cómo optimizar esto?

Respuesta

19

supongo que está utilizando MySQL, así que esto es lo que puede intentar

create_table :global_feeds, {:id => false} do |t| 
    t.string :guid 
    t.text :title 
    t.text :subtitle 
    t.timestamps 
end 
execute "ALTER TABLE global_feeds ADD PRIMARY KEY (guid);" 

Si no estás en MySQL debe cambiar la consulta en el comando execute a trabajar en su motor de base de datos. No estoy seguro si puedes hacer eso en SQLite sin embargo. Y no se olvide de poner esta línea en alguna parte en el modelo global_feed.rb:

set_primary_key :guid 

De todos modos se van a obtener el máximo provecho de los carriles, mientras que usted se está pegando a sus convenciones. Cambiar el nombre y el tipo de la clave principal podría no ser una muy buena idea.

+0

Desafortunadamente, esto sigue siendo dos sentencias de SQL como la mía. Acaba de voltear el orden de las operaciones: primero está definiendo el tipo de columna y luego especificando la clave primaria. – Ryan

+0

Supongo que no puedes hacer eso en una sola operación, pero supongo que no tiene nada de malo. Está perfectamente bien que la migración tenga dos declaraciones para casos un poco más complejos. –

+0

Además, no estoy seguro de si ActiveRecord funciona bien con claves primarias no enteras en absoluto. –

4

Debe usar #column en lugar de #string. Por ejemplo:

create_table(:global_feeds, :primary_key => 'guid') do |t| 
    t.column :guid, "varchar(25)", :null => false 
    ... 
end 

Tenga en cuenta que el tipo varchar no es portable a bases de datos distinto a MySQL.

+0

'error de sintaxis, inesperado '(', esperando keyword_end t.column: guid,: varchar (26),: null => false' Con ello apuntando al paréntesis al final de varchar – Ryan

+0

Correcto. Utilizar' " varchar (25) "' en lugar de ': varchar (25)'. – JellicleCat

3

Esto es posible en Rails 3. Probar:

def self.up 
    create_table(:signups, :id => false) do |t| 
     t.string :token, :primary => true 

la salida de este quid de una gran solución para el uso de UUID como una col clave principal: https://gist.github.com/937739

+2

No funcionó para mí en Rails 4 + MySQL – dolzenko

+0

Ver respuesta por @kakoni –

22

En Rails 4 se puede hacer;

create_table :global_feeds, id: false do |t| 
    t.string :guid, primary_key: true 
... 
end 
+1

Funciona perfectamente en rieles 4! –

+1

esto no debe ser una cadena, mysql con uuid debe ser un binario (16) – Seed

+1

Funciona en Rails 5 :-) – Maybe1

0

En los carriles 5, para las tangas que recibieron problema ArgumentError: Index name '*' on table '*' already exists cuando rails db:setup con la migración a partir de las siguientes obras, @kakoni para mí

create_table(:global_feeds, primary_key: :guid, id: false) do |t| 
    t.string :guid 
... 
end 

Para obtener más información, consulte create_table.

Cuestiones relacionadas