postgresql - docs - github phoenix framework
Configuración de Phoenix Framework y Ecto para usar UUID: ¿cómo insertar el valor generado? (2)
EDITAR: He actualizado esta respuesta a Ecto v2.0. Puedes leer la respuesta anterior al final.
Ecto v2
El manejo de UUID en Ecto se ha vuelto mucho más sencillo desde la respuesta original. Ecto tiene dos tipos de ID :id
y :binary_id
. El primero es un ID entero como sabemos por las bases de datos, el segundo es un binario específico de la base de datos. Para Postgres, es un UUID.
Para tener UUID como claves principales, primero especifíquelos en su migración:
create table(:posts, primary_key: false) do
add :id, :binary_id, primary_key: true
end
Luego en su módulo de modelo (fuera del bloque de schema
):
@primary_key {:id, :binary_id, autogenerate: true}
Cuando especifique la opción :autogenerate
para :binary_id
, Ecto garantizará que el adaptador o la base de datos lo generará por usted. Sin embargo, todavía puede generarlo manualmente si lo prefiere. Por cierto, podría haber usado :uuid
en su migración y Ecto.UUID
en su esquema en lugar de :binary_id
, el beneficio de :binary_id
es que es portátil en todas las bases de datos.
Ecto v1
Debe decirle a su base de datos cómo generar automáticamente el UUID para usted. O necesitas generar uno desde el lado de la aplicación. Depende de cuál prefieras.
Antes de continuar, es importante decir que está utilizando :uuid
que devolverá los binarios en lugar de los UUID legibles. Es muy probable que desee utilizar Ecto.UUID
que lo formateará como una cadena (aaaa-bbb-ccc -...) y eso es lo que usaré a continuación.
Generando en la base de datos
En su migración, defina un valor predeterminado para el campo:
add :id, :uuid, primary_key: true, default: fragment("uuid_generate_v4()")
Supongo que se está ejecutando en PostgreSQL. Debe instalar la extensión uuid-ossp con CREATE EXTENSION "uuid-ossp"
en pgAdmin o agregar execute "CREATE EXTENSION /"uuid-ossp/""
en la migración. Más información sobre el generador UUID se puede encontrar aquí .
De vuelta a Ecto, en su modelo, pídale a Ecto que lea el campo de la base de datos después de insertar / actualizar:
@primary_key {:id, Ecto.UUID, read_after_writes: true}
Ahora, cuando inserte, la base de datos generará un valor predeterminado y Ecto lo leerá.
Generando en la aplicación
Deberá definir un módulo que inserte el UUID por usted:
defmodule MyApp.UUID do
def put_uuid(changeset) do
Ecto.Changeset.put_change(changeset, :id, Ecto.UUID.generate())
end
end
Y utilízalo como devolución de llamada:
def model do
quote do
use Ecto.Model
@primary_key {:id, Ecto.UUID, []}
@foreign_key_type Ecto.UUID
before_insert MyApp.UUID, :put_uuid, []
end
end
before_insert
es una devolución de llamada y llamará al módulo dado en la función dada con los argumentos dados, con un conjunto de cambios que representa lo que se inserta y se da como primer argumento.
Eso debería ser todo. Por cierto, existe la posibilidad de que esto sea más eficiente en el futuro. :)
Hace unos días comencé a usar Elixir y Phoenix Framework (v 0.12.0) con una base de datos de Postgres. Estoy tratando de crear una tabla que tenga una clave primaria UUID, que prefiero por encima del valor predeterminado secuencial.
Después de usar mix phoenix.gen.html
para generar el modelo y los archivos de migración y seguir los otros pasos en los documentos de Phoenix, he cambiado
def model do
quote do
use Ecto.Model
end
end
en web.ex
a
def model do
quote do
use Ecto.Model
@primary_key {:id, :uuid, []}
@foreign_key_type :uuid
end
end
como se menciona en los documentos ecto. También he cambiado la migración a
create table(:tblname, primary_key: false) do
add :id, :uuid, primary_key: true
[other columns]
end
Desafortunadamente, cuando intento agregar una entrada a la tabla desde el formulario generado automáticamente, aparece un error porque el id
es nulo. Si agrego manualmente una columna de id
al modelo, recibo un error de que la columna ya existe. Si me olvido de establecer primary_key
en falso en la table/2
y primary_key
la columna de id
, la tabla se genera con una columna de id
secuencial.
¿Necesito configurar manualmente la id
en el conjunto de cambios o he cometido un error al configurar mi aplicación para usar los UUID? Gracias por adelantado
También al crear una nueva opción de --binary-id
proyecto --binary-id
para usar UUID como clave principal predeterminada. (Iniciando Ecto v2 )
mix phx.new project_name --binary-id