Om du använder ActiveRecord som följer med Rails med en av dess adaptrar, är den enda formella mappningen av databastyp till Rails eller Ruby typ som sker vanligtvis definierad i NATIVE_DATABASE_TYPES
konstant i adaptern som returneras via dess native_database_types
metod. För PostgreSQL i Rails 3.2.x, det vill säga i ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
som finns här
. Så för den adaptern mappas den "binära" typen i Rails till typen "bytea" i PG. För vissa typer kan du åsidosätta den databastypen som den mappar till med en pärla som heter activerecord-native_db_types_override
a> . Men vi vill använda stora föremål, så...
Migreringar
Som Jim Deville noterade i kommentarerna kan du ange den anpassade kolumnen i tabellen som:
t.column :some_oid, 'blob_oid', :null => false
Om du behöver göra ännu mer som inte är standard, kan du också använda en execute("SQL GOES HERE;")
för att skapa tabellen med rak SQL. Och om du har ett befintligt äldre schema eller SQL-ändringar som har gjorts utanför migreringarna, överväg att använda structure.sql (config.active_record.schema_format = :sql
alternativet i config/application.rb
och gör sedan:rake db:structure:dump
).
Stora objekt Läs/Skriv/Kontrollera längd/Ta bort
Kopierat med några ändringar för att förtydliga, etc. från:https://github.com/diogob/carrierwave-postgresql/blob/v0.1.0/lib/carrierwave/storage/postgresql_lo.rb :
Uppdaterad :vi kan men behöver inte sätta en början före lo_read/lo_write/lo_lseek och gör lo_close i säkerställ blockering eftersom PG-dokumentation "Alla stora objektbeskrivningar som förblir öppna i slutet av en transaktion kommer att stängas automatiskt." (tack till Diogo för den informationen)
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
Istället för connection
, använd den råa anslutningen från modellen eller basen, t.ex. ActiveRecord::Base.connection.raw_connection
(se detta
).
(...).transaction
ringer transaktion på modell eller bas, t.ex. ActiveRecord::Base.transaction
(se detta
).
identifier
är den oid som du antingen behöver skicka in/ställa in eller få genom att bara göra en connection.lo_creat
.
Andra exempel/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
Det senare och några svar här föreslår att du kanske vill överväga lagring av stora filer separat från DB, t.ex. så att du kan använda molnlagring. Men om bara lagra sökvägarna/ID:n till externa filer som inte är hanteras av DB förlorar du ACID-konsistens (en eller flera DB-poster kan peka på en eller flera filer som inte finns där eller en eller flera filer som inte har en eller flera associerade poster i databasen). Ett annat argument för att lagra filer på filsystemet är att du kan streama filer, men PG large object lagrar filer på filsystemet på ett sätt som hanteras av postgres för att både säkerställa ACID-konsistens och tillåta streaming (vilket du inte kan göra med en vanlig BLOB) /Rails binär typ). Så, det beror bara på; vissa tycker att lagring i separat lagring med hjälp av sökvägsreferenser är ett bättre alternativ, och vissa föredrar ACID-konsistens via stora objekt.
Det enkla sättet
Använd bara CarrierWave och carrierwave-postgresql .