Als ActiveRecord wordt gebruikt dat bij Rails wordt geleverd met een van zijn adapters, wordt de enige formele toewijzing van het databasetype aan het Rails- of Ruby-type die plaatsvindt, meestal gedefinieerd in de NATIVE_DATABASE_TYPES
constante in de adapter die wordt geretourneerd via zijn native_database_types
methode. Voor PostgreSQL in Rails 3.2.x is dat in ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
dat is hier
. Dus voor die adapter verwijst het "binaire" type in Rails naar het "bytea" -type in PG. Voor sommige typen kunt u dat databasetype overschrijven waarnaar het verwijst met behulp van een juweeltje genaamd activerecord-native_db_types_override . Maar we willen grote objecten gebruiken, dus...
Migraties
Zoals Jim Deville opmerkte in de opmerkingen, kunt u de aangepaste getypte kolom in de tabel specificeren zoals:
t.column :some_oid, 'blob_oid', :null => false
Als u nog meer moet doen dat niet-standaard is, kunt u ook een execute("SQL GOES HERE;")
gebruiken om de tabel te maken met behulp van rechte SQL. En als u een bestaand verouderd schema of SQL-wijzigingen heeft die buiten de migraties om zijn aangebracht, overweeg dan het gebruik van structure.sql (config.active_record.schema_format = :sql
optie in config/application.rb
en doe dan:rake db:structure:dump
).
Grote objecten lezen/schrijven/controleren lengte/verwijderen
Gekopieerd met enkele aanpassingen ter verduidelijking, enz. van:https://github.com/diogob/carrierwave-postgresql/blob/v0.1.0/lib/carrierwave/storage/postgresql_lo.rb :
Bijgewerkt :we kunnen, maar hoeven geen begin te maken vóór de lo_read/lo_write/lo_lseek en doen lo_close in zorgen voor blokkering omdat per PG-documentatie "Alle grote objectbeschrijvingen die aan het einde van een transactie open blijven, worden automatisch gesloten." (met dank aan Diogo voor die info)
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
In plaats van connection
, gebruik de onbewerkte verbinding van het model of de basis, b.v. ActiveRecord::Base.connection.raw_connection
(zie dit
).
(...).transaction
belt transactie op model of basis, b.v. ActiveRecord::Base.transaction
(zie dit
).
identifier
is de oid die je ofwel moet doorgeven/instellen of krijgen door gewoon een connection.lo_creat
te doen .
Andere voorbeelden/info:
- http://rubydoc.info/github/nedforce/devcms-core/ DbFile
- https://github.com/nedforce/devcms-core
- http://my.safaribooksonline.com/ book/web-development/ruby/9780596510329/database/largebinary_objects
De laatste en enkele antwoorden hier suggereren dat u de opslag van grote bestanden los van de DB zou kunnen overwegen, b.v. zodat u cloudopslag kunt gebruiken. Maar sla alleen de paden/ID's op naar externe bestanden die niet . zijn beheerd door de DB, verliest u de ACID-consistentie (een of meer DB-records kunnen verwijzen naar een of meer bestanden die er niet zijn of een of meer bestanden die niet een of meer bijbehorende records in de database hebben). Een ander argument voor het opslaan van bestanden op het bestandssysteem is dat je bestanden kunt streamen, maar PG large object slaat bestanden op het bestandssysteem op een manier op die wordt beheerd door postgres om zowel ACID-consistentie te garanderen als streaming toe te staan (wat je niet kunt doen met een normale BLOB /Rails binair type). Het hangt er dus gewoon van af; sommigen vinden opslag in aparte opslag met behulp van padverwijzingen een betere optie, en sommigen geven de voorkeur aan ACID-consistentie via grote objecten.
De gemakkelijke manier
Gebruik gewoon CarrierWave en carrierwave-postgresql .