Hvis du bruger ActiveRecord, der følger med Rails med en af dets adaptere, er den eneste formelle tilknytning af databasetype til Rails eller Ruby type, der sker, typisk defineret i NATIVE_DATABASE_TYPES
konstant i adapteren, som returneres via dens native_database_types
metode. For PostgreSQL i Rails 3.2.x, dvs. i ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
som er her
. Så for den adapter er den "binære" type i Rails knyttet til typen "bytea" i PG. For nogle typer kan du tilsidesætte den databasetype, som den er knyttet til ved hjælp af en perle kaldet activerecord-native_db_types_override
a> . Men vi vil gerne bruge store genstande, så...
Migreringer
Som Jim Deville bemærkede i kommentarerne, kan du angive den brugerdefinerede kolonne i tabellen som:
t.column :some_oid, 'blob_oid', :null => false
Hvis du har brug for at gøre endnu mere, der ikke er standard, kan du også bruge en execute("SQL GOES HERE;")
at oprette tabellen ved hjælp af lige SQL. Og hvis du har et eksisterende ældre skema eller SQL-ændringer, der er foretaget uden for migreringerne, kan du overveje at bruge structure.sql (config.active_record.schema_format = :sql
mulighed i config/application.rb
og gør derefter:rake db:structure:dump
).
Store objekter Læs/Skriv/Tjek længde/Slet
Kopieret med nogle ændringer for at præcisere osv. fra:https://github.com/diogob/carrierwave-postgresql/blob/v0.1.0/lib/carrierwave/storage/postgresql_lo.rb :
Opdateret :vi kan, men behøver ikke at begynde før lo_read/lo_write/lo_lseek og gør lo_close i sikre blokering, fordi pr. PG-dokumentation "Alle store objektbeskrivelser, der forbliver åbne i slutningen af en transaktion, lukkes automatisk." (tak til Diogo for den 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
I stedet for connection
, brug råforbindelsen fra modellen eller basen, f.eks. ActiveRecord::Base.connection.raw_connection
(se dette
).
(...).transaction
kalder transaktion på model eller base, f.eks. ActiveRecord::Base.transaction
(se dette
).
identifier
er den oid, som du enten skal sende ind/indstille eller få ved blot at lave en connection.lo_creat
.
Andre eksempler/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
Sidstnævnte og nogle svar her foreslår, at du måske vil overveje opbevaring af store filer adskilt fra DB, f.eks. så du kan bruge cloud storage. Men hvis kun gemmer stierne/ID'erne til eksterne filer, der ikke er administreres af DB, mister du ACID-konsistens (en eller flere DB-poster kan pege på en eller flere filer, der ikke er der, eller der kan eksistere en eller flere filer, der ikke har en eller flere tilknyttede poster i databasen). Et andet argument for at gemme filer på filsystemet er, at du kan streame filer, men PG large object gemmer filer på filsystemet på en måde, der administreres af postgres for både at sikre ACID-konsistens og tillade streaming (hvilket du ikke kan med en normal BLOB) /Binær type skinner). Så det kommer bare an på; nogle finder lagring i separat lager ved hjælp af sti-referencer en bedre mulighed, og nogle foretrækker ACID-konsistens via store objekter.
Den nemme måde
Brug bare CarrierWave og carrierwave-postgresql .