2

Railsアプリのデータベースに大きなオブジェクトを保存する必要があります。SQLでテーブルを作成できると思います

CREATE TABLE files (
id serial NOT NULL,
name string NOT NULL,
blob_oid oid NUT NULL
)

そして、データをRubyに次のように保存します

conn.exec("BEGIN")
lo = conn.lo_import(data)
conn.exec("COMMIT")
file = File.new
file.name = file_name; file.blob_oid = lo.id
file.save

まず第一に、これは正しいですか?次に、FileinRailsのモデルをどのように説明しますか。Friend.blob_oidRailsのデータ型は何ですか?Railsでの移行を使用してファイルテーブルを作成できますか?

4

1 に答える 1

5

アダプターの1つでRailsに付属しているActiveRecordを使用する場合、発生するデータベースタイプからRailsまたはRubyタイプへの唯一の正式なマッピングは、通常、そのメソッドNATIVE_DATABASE_TYPESを介して返されるアダプターの定数で定義されます。native_database_typesRails 3.2.xのPostgreSQLの場合、ここにActiveRecord::ConnectionAdapters::PostgreSQLAdapterあります。したがって、そのアダプターの場合、Railsの「binary」タイプはPGの「bytea」タイプにマップされます。一部のタイプでは、 activerecord-native_db_types_overrideというgemを使用して、マップするデータベースタイプをオーバーライドできます。しかし、大きなオブジェクトを使用したいので...

移行

Jim Devilleがコメントで指摘したように、次のようにテーブルでカスタム型の列を指定できます。

t.column :some_oid, 'blob_oid', :null => false

非標準の処理をさらに行う必要がある場合は、execute("SQL GOES HERE;")を使用してストレートSQLを使用してテーブルを作成することもできます。また、移行の外部で行われた既存のレガシースキーマまたはSQLの変更がある場合は、structure.sqlの使用を検討してください(config.active_record.schema_format = :sqlオプションを入力しconfig/application.rbてから実行してください:) rake db:structure:dump

大きなオブジェクトの読み取り/書き込み/長さの確認/削除

明確にするためにいくつかの変更を加えてコピーしました。https ://github.com/diogob/carrierwave-postgresql/blob/v0.1.0/lib/carrierwave/storage/postgresql_lo.rb :

更新: PGのドキュメントによると、「トランザクションの終了時に開いたままの大きなオブジェクト記述子は自動的に閉じられる」ため、lo_read / lo_write / lo_lseekの前に開始し、ensureブロックでlo_closeを実行する必要はありません。(その情報を提供してくれたDiogoに感謝します)

    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

の代わりにconnection、モデルまたはベースからの生の接続を使用します。たとえば、ActiveRecord::Base.connection.raw_connectionこれを参照)。

(...).transactionモデルまたはベースでトランザクションを呼び出しています。たとえばActiveRecord::Base.transactionこれを参照)。

identifierは、渡す/設定するか、または単に実行することで取得する必要があるOIDですconnection.lo_creat

その他の例/情報:

後者とここでのいくつかの回答は、たとえばクラウドストレージを使用できるように、DBとは別に大きなファイルのストレージを検討することをお勧めします。ただし、パス/IDを保存していない外部ファイルにのみ保存する場合DBによって管理されると、ACIDの一貫性が失われます(1つ以上のDBレコードが、存在しない1つ以上のファイルを指しているか、データベースに1つ以上の関連レコードがない1つ以上のファイルが存在する可能性があります)。ファイルシステムにファイルを保存するためのもう1つの議論は、ファイルをストリーミングできるということですが、PGラージオブジェクトはpostgresによって管理される方法でファイルをファイルシステムに保存し、ACIDの一貫性を確保し、ストリーミングを許可します(通常のBLOBでは実行できません)。 / Railsバイナリタイプ)。だから、それはただ依存します。パス参照を使用して別のストレージに保存する方が良いオプションであると考える人もいれば、ラージオブジェクトを介したACIDの一貫性を好む人もいます。

簡単な方法

CarrierWavecarrierwave-postgresqlを使用するだけです。

于 2013-02-07T15:21:23.817 に答える