Se si utilizza ActiveRecord fornito con Rails con uno dei suoi adattatori, l'unica mappatura formale del tipo di database al tipo Rails o Ruby che si verifica è in genere definita in NATIVE_DATABASE_TYPES
costante nell'adattatore che viene restituito tramite i suoi native_database_types
metodo. Per PostgreSQL in Rails 3.2.x, cioè in ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
che è qui
. Quindi, per quell'adattatore, il tipo "binary" in Rails viene mappato al tipo "bytea" in PG. Per alcuni tipi, puoi sovrascrivere quel tipo di database a cui è mappato usando una gem chiamata activerecord-native_db_types_override . Ma vogliamo usare oggetti di grandi dimensioni, quindi...
Migrazioni
Come ha notato Jim Deville nei commenti, puoi specificare la colonna digitata personalizzata nella tabella come:
t.column :some_oid, 'blob_oid', :null => false
Se hai bisogno di fare ancora di più che non sono standard, puoi anche usare un execute("SQL GOES HERE;")
per creare la tabella utilizzando SQL diretto. E, se disponi di uno schema legacy esistente o di modifiche SQL apportate al di fuori delle migrazioni, considera l'utilizzo di structure.sql (config.active_record.schema_format = :sql
opzione in config/application.rb
e poi fai:rake db:structure:dump
).
Leggi/Scrivi/Controlla lunghezza/Elimina oggetti di grandi dimensioni
Copiato con alcune modifiche per chiarire, ecc. da:https://github.com/diogob/carrierwave-postgresql/blob/v0.1.0/lib/carrierwave/storage/postgresql_lo.rb :
Aggiornato :possiamo, ma non è necessario, iniziare prima di lo_read/lo_write/lo_lseek e fare lo_close nel blocco garantire perché per Documentazione PG "Tutti i descrittori di oggetti di grandi dimensioni che rimangono aperti alla fine di una transazione verranno chiusi automaticamente." (grazie a Diogo per le informazioni)
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
Invece di connection
, utilizzare la connessione grezza del modello o della base, ad es. ActiveRecord::Base.connection.raw_connection
(vedi questo
).
(...).transaction
chiama la transazione sul modello o sulla base, ad es. ActiveRecord::Base.transaction
(vedi questo
).
identifier
è l'oid che devi passare/impostare o ottenere semplicemente facendo un connection.lo_creat
.
Altri esempi/informazioni:
- http://rubydoc.info/github/nedforce/devcms-core/ File Db
- https://github.com/nedforce/devcms-core
- http://my.safaribooksonline.com/ book/web-development/ruby/9780596510329/database/largebinary_objects
Quest'ultimo e alcune risposte qui suggerisci di considerare l'archiviazione di file di grandi dimensioni separata dal DB, ad es. in modo da poter utilizzare il cloud storage. Ma, se solo archivia i percorsi/ID di file esterni che non gestiti dal DB, si perde la coerenza ACID (uno o più record DB potrebbero puntare a uno o più file che non ci sono oppure potrebbero esistere uno o più file che non hanno uno o più record associati nel database). Un altro argomento per l'archiviazione di file nel file system è che è possibile eseguire lo streaming di file, ma l'oggetto di grandi dimensioni PG archivia i file nel file system in un modo gestito da postgres per garantire la coerenza ACID e consentire lo streaming (cosa che non è possibile fare con un normale BLOB /Tipo binario di binari). Quindi, dipende solo; alcuni ritengono che l'archiviazione in una memoria separata utilizzando i riferimenti di percorso sia un'opzione migliore e alcuni preferiscono la coerenza ACID tramite oggetti di grandi dimensioni.
Il modo più semplice
Basta usare CarrierWave e carrierwave-postgresql .