Esta parte de tu pregunta:
Sé que podemos crearlo manualmente en PostgreSQL, pero la "magia" con Active Record es que la base de datos se puede recrear con todos los modelos.
me dice que realmente está buscando una forma de integrar las funciones de PostgreSQL con el proceso normal de migración de Rails y las tareas de Rake como db:schema:load
.
Agregar y quitar funciones en las migraciones es fácil:
def up
connection.execute(%q(
create or replace function ...
))
end
def down
connection.execute(%q(
drop function ...
))
end
Necesitas usar up
separado y down
métodos en lugar de un único change
método porque ActiveRecord no tendrá idea de cómo aplicar y mucho menos revertir la creación de una función. Y usas connection.execute
para alimentar la definición de función sin procesar a PostgreSQL. También puedes hacer esto con un reversible
dentro de change
:
def change
reversible do |dir|
dir.up do
connection.execute(%q(
create or replace function ...
))
end
dir.down do
connection.execute(%q(
drop function ...
))
end
end
end
pero lo encuentro más ruidoso que up
y down
.
Sin embargo, schema.rb
y las tareas habituales de Rake que funcionan con schema.rb
(como db:schema:load
y db:schema:dump
) no sabrá qué hacer con las funciones de PostgreSQL y otras cosas que ActiveRecord no comprende. Sin embargo, hay una forma de evitar esto, puede elegir usar un structure.sql
archivo en lugar de schema.rb
configurando:
config.active_record.schema_format = :sql
en su config/application.rb
expediente. Después de eso, db:migrate
escribirá un db/structure.sql
(que es solo un volcado SQL sin formato de su base de datos PostgreSQL sin sus datos) en lugar de db/schema.rb
. También usará diferentes tareas Rake para trabajar con structure.sql
:
db:structure:dump
en lugar dedb:schema:dump
db:structure:load
en lugar dedb:schema:load
Todo lo demás debería funcionar igual.
Este enfoque también le permite usar otras cosas en su base de datos que ActiveRecord no comprenderá:restricciones CHECK, disparadores, valores predeterminados de columna no simples, ...