Wenn Sie ActiveRecord verwenden, das mit Rails mit einem seiner Adapter geliefert wird, wird die einzige formale Zuordnung des Datenbanktyps zum Rails- oder Ruby-Typ, die normalerweise stattfindet, in NATIVE_DATABASE_TYPES
definiert Konstante im Adapter, die über seine native_database_types
zurückgegeben wird Methode. Für PostgreSQL in Rails 3.2.x ist dies in ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
das ist hier
. Für diesen Adapter wird also der Typ „binary“ in Rails dem Typ „bytea“ in PG zugeordnet. Bei einigen Typen können Sie diesen Datenbanktyp überschreiben, dem er zugeordnet ist, indem Sie ein Gem namens activerecord-native_db_types_override . Aber wir wollen große Objekte verwenden, also...
Migrationen
Wie Jim Deville in den Kommentaren angemerkt hat, können Sie die benutzerdefinierte Spalte in der Tabelle wie folgt angeben:
t.column :some_oid, 'blob_oid', :null => false
Wenn Sie noch mehr tun müssen, was nicht dem Standard entspricht, können Sie auch ein execute("SQL GOES HERE;")
verwenden um die Tabelle mit direktem SQL zu erstellen. Und wenn Sie über ein vorhandenes Legacy-Schema oder SQL-Änderungen verfügen, die außerhalb der Migrationen vorgenommen wurden, sollten Sie die Verwendung von structure.sql (config.active_record.schema_format = :sql
) in Betracht ziehen Option in config/application.rb
und dann tun:rake db:structure:dump
).
Große Objekte lesen/schreiben/Länge prüfen/löschen
Mit einigen Modifikationen zur Verdeutlichung usw. kopiert von:https://github.com/diogob/carrierwave-postgresql/blob/v0.1.0/lib/carrierwave/storage/postgresql_lo.rb :
Aktualisiert :Wir können, müssen aber nicht, ein begin vor lo_read/lo_write/lo_lseek setzen und lo_close im Sicherstellungsblock ausführen, weil per PG-Dokumentation "Alle großen Objektdeskriptoren, die am Ende einer Transaktion offen bleiben, werden automatisch geschlossen." (danke an Diogo für diese 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
Statt connection
, verwenden Sie die Rohverbindung vom Modell oder Sockel, z. ActiveRecord::Base.connection.raw_connection
(siehe hier
).
(...).transaction
ruft Transaktion auf Modell oder Basis auf, z. ActiveRecord::Base.transaction
(Siehe dies
).
identifier
ist die OID, die Sie entweder übergeben/setzen müssen oder die Sie erhalten, indem Sie einfach ein connection.lo_creat
ausführen .
Weitere Beispiele/Infos:
- http://rubydoc.info/github/nedforce/devcms-core/ DbDatei
- https://github.com/nedforce/devcms-core
- http://my.safaribooksonline.com/ book/web-development/ruby/9780596510329/database/largebinary_objects
Letzteres und einige Antworten hier schlagen vor, dass Sie die Speicherung großer Dateien getrennt von der DB in Betracht ziehen sollten, z. damit Sie Cloud-Speicher verwenden können. Aber wenn Sie nur die Pfade/IDs zu externen Dateien speichern, die nicht sind von der DB verwaltet werden, verlieren Sie die ACID-Konsistenz (ein oder mehrere DB-Datensätze könnten auf eine oder mehrere Dateien verweisen, die nicht vorhanden sind, oder es könnten eine oder mehrere Dateien existieren, die keinen oder mehrere zugehörige Datensätze in der Datenbank haben). Ein weiteres Argument für das Speichern von Dateien im Dateisystem ist, dass Sie Dateien streamen können, aber PG Large Object speichert Dateien im Dateisystem auf eine von Postgres verwaltete Weise, um sowohl die ACID-Konsistenz zu gewährleisten als auch das Streaming zu ermöglichen (was Sie mit einem normalen BLOB nicht tun können /Rails-Binärtyp). Es kommt also nur darauf an; einige halten das Speichern in separatem Speicher unter Verwendung von Pfadreferenzen für eine bessere Option, und einige bevorzugen ACID-Konsistenz über große Objekte.
Der einfache Weg
Verwenden Sie einfach CarrierWave und carrierwave-postgresql .