Si usa ActiveRecord que viene con Rails con uno de sus adaptadores, la única asignación formal del tipo de base de datos al tipo Rails o Ruby que ocurre generalmente se define en NATIVE_DATABASE_TYPES
constante en el adaptador que se devuelve a través de sus native_database_types
método. Para PostgreSQL en Rails 3.2.x, eso está en ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
que está aquí
. Entonces, para ese adaptador, el tipo "binario" en Rails se asigna al tipo "bytea" en PG. Para algunos tipos, puede anular ese tipo de base de datos al que se asigna usando una gema llamada activerecord-native_db_types_override . Pero queremos usar objetos grandes, así que...
Migraciones
Como señaló Jim Deville en los comentarios, puede especificar la columna escrita personalizada en la tabla como:
t.column :some_oid, 'blob_oid', :null => false
Si necesita hacer aún más que no sea estándar, también puede usar execute("SQL GOES HERE;")
para crear la tabla usando SQL directo. Y, si tiene un esquema heredado existente o cambios de SQL que se han realizado fuera de las migraciones, considere usar structure.sql (config.active_record.schema_format = :sql
opción en config/application.rb
y luego haz:rake db:structure:dump
).
Objetos grandes Leer/Escribir/Comprobar longitud/Eliminar
Copiado con algunas modificaciones para aclarar, etc. de:https://github.com/diogob/carrierwave-postgresql/blob/v0.1.0/lib/carrierwave/storage/postgresql_lo.rb :
Actualizado :podemos, pero no es necesario, poner un comienzo antes de lo_read/lo_write/lo_lseek y hacer lo_close en el bloque de garantía porque por Documentación de PG "Cualquier descriptor de objeto grande que permanezca abierto al final de una transacción se cerrará automáticamente". (gracias a Diogo por esa información)
require 'pg'
...
def read
(...).transaction do
lo = connection.lo_open(identifier)
content = connection.lo_read(lo, file_length)
connection.lo_close(lo)
content
end
end
def write(file)
(...).transaction do
lo = connection.lo_open(identifier, ::PG::INV_WRITE)
size = connection.lo_write(lo, file.read)
connection.lo_close(lo)
size
end
end
def delete
connection.lo_unlink(identifier)
end
def file_length
(...).transaction do
lo = connection.lo_open(identifier)
size = connection.lo_lseek(lo, 0, 2)
connection.lo_close(lo)
size
end
end
En lugar de connection
, use la conexión sin procesar del modelo o la base, p. ActiveRecord::Base.connection.raw_connection
(ver esto
).
(...).transaction
está llamando a la transacción en el modelo o la base, p. ActiveRecord::Base.transaction
(ver esto
).
identifier
es el oid que necesita pasar/establecer u obtener simplemente haciendo connection.lo_creat
.
Otros ejemplos/información:
- http://rubydoc.info/github/nedforce/devcms-core/ ArchivoDb
- https://github.com/nedforce/devcms-core
- http://my.safaribooksonline.com/ libro/desarrollo web/ruby/9780596510329/database/largebinary_objects
Este último y algunas respuestas -mb-en-una-base-de-datos">aquí sugiera que es posible que desee considerar el almacenamiento de archivos grandes separados de la base de datos, p. para que pueda usar el almacenamiento en la nube. Pero, si solo almacena las rutas/ID de archivos externos que no administrado por la base de datos, pierde la consistencia ACID (uno o más registros de la base de datos podrían apuntar a uno o más archivos que no están allí o uno o más archivos podrían existir que no tienen uno o más registros asociados en la base de datos). Otro argumento para almacenar archivos en el sistema de archivos es que puede transmitir archivos, pero el objeto grande PG almacena archivos en el sistema de archivos de una manera administrada por postgres para garantizar la coherencia ACID y permitir la transmisión (lo que no puede hacer con un BLOB normal /Rails tipo binario). Entonces, solo depende; algunos encuentran que el almacenamiento en almacenamiento separado usando referencias de ruta es una mejor opción, y algunos prefieren la consistencia ACID a través de objetos grandes.
La Manera Fácil
Simplemente use CarrierWave y carrierwave-postgresql .