Jika menggunakan ActiveRecord yang disertakan dengan Rails dengan salah satu adaptornya, satu-satunya pemetaan formal tipe database ke tipe Rails atau Ruby yang terjadi biasanya ditentukan dalam NATIVE_DATABASE_TYPES
konstanta di adaptor yang dikembalikan melalui native_database_types
metode. Untuk PostgreSQL di Rails 3.2.x, yaitu di ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
yang di sini
. Jadi, untuk adaptor itu, tipe "biner" di Rails dipetakan ke tipe "bytea" di PG. Untuk beberapa jenis, Anda dapat mengganti jenis basis data yang dipetakannya menggunakan permata bernama activerecord-native_db_types_override . Tapi, kami ingin menggunakan objek besar, jadi...
Migrasi
Seperti yang dicatat Jim Deville di komentar, Anda dapat menentukan kolom yang diketik khusus di tabel seperti:
t.column :some_oid, 'blob_oid', :null => false
Jika Anda perlu melakukan lebih banyak lagi yang non-standar, Anda juga dapat menggunakan execute("SQL GOES HERE;")
untuk membuat tabel menggunakan SQL langsung. Dan, jika Anda memiliki skema lama atau perubahan SQL yang telah dibuat di luar migrasi, pertimbangkan untuk menggunakan structure.sql (config.active_record.schema_format = :sql
pilihan di config/application.rb
dan kemudian lakukan:rake db:structure:dump
).
Objek Besar Baca/Tulis/Periksa Panjang/Hapus
Disalin dengan beberapa modifikasi untuk memperjelas, dll. dari:https://github.com/diogob/carrierwave-postgresql/blob/v0.1.0/lib/carrierwave/storage/postgresql_lo.rb :
Diperbarui :kita dapat tetapi tidak perlu memulai sebelum lo_read/lo_write/lo_lseek dan melakukan lo_close di blok sure karena per Dokumentasi PG "Setiap deskriptor objek besar yang tetap terbuka pada akhir transaksi akan ditutup secara otomatis." (terima kasih kepada Diogo atas infonya)
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
Alih-alih connection
, gunakan koneksi mentah dari model atau basis, mis. ActiveRecord::Base.connection.raw_connection
(lihat ini
).
(...).transaction
memanggil transaksi pada model atau basis, mis. ActiveRecord::Base.transaction
(lihat ini
).
identifier
adalah oid yang harus Anda lewati/set atau dapatkan hanya dengan melakukan connection.lo_creat
.
Contoh/info lain:
- http://rubydoc.info/github/nedforce/devcms-core/ DbFile
- https://github.com/nedforce/devcms-core
- http://my.safaribooksonline.com/ buku/pengembangan web/ruby/9780596510329/database/largebinary_objects
Yang terakhir dan beberapa jawaban di sini menyarankan bahwa Anda mungkin ingin mempertimbangkan penyimpanan file besar yang terpisah dari DB, mis. sehingga Anda dapat menggunakan penyimpanan cloud. Tapi, jika hanya menyimpan path/ID ke file eksternal yang bukan dikelola oleh DB, Anda kehilangan konsistensi ACID (satu atau lebih catatan DB dapat menunjuk ke satu atau lebih file yang tidak ada atau satu atau lebih file bisa ada yang tidak memiliki satu atau lebih catatan terkait dalam database). Argumen lain untuk menyimpan file pada sistem file adalah Anda dapat melakukan streaming file, tetapi objek besar PG menyimpan file pada sistem file dengan cara yang dikelola oleh postgres untuk memastikan konsistensi ACID dan memungkinkan streaming (yang tidak dapat Anda lakukan dengan BLOB normal /Rails tipe biner). Jadi, itu hanya tergantung; beberapa menemukan penyimpanan di penyimpanan terpisah menggunakan referensi jalur sebagai opsi yang lebih baik, dan beberapa lebih memilih konsistensi ACID melalui Objek Besar.
Cara Mudah
Cukup gunakan CarrierWave dan carrierwave-postgresql .