2012-02-11 10 views
2

私のモデルの1つに、データベースに格納する前に圧縮したい巨大なテキスト列があります(ディスク容量を節約するためではありませんが、それがここに Railsでデータベースに格納する前に属性を透過的に圧縮する

は私が書いてみました拡張機能の関連ですが、何らかの理由で、これは生産で動作していない場合

私のデータベースはPostgreSQLのある)私のアプリサーバに私のDBサーバからネットワーク経由で圧縮されていないフィールドを送信します(実際にデータベースに格納されているデータは、Zlibの出力(例えば "A \ xEB \ xD3 \ xF2Oy = \ x9C \ x7F5 \ xE9 \ xC44 \ x01M")の代わりに16進数のように見えます(例: "34bee1c2d099ba21da3ac533d5f99cda2654feb73985430df39c5ffd8fbf9d9ff3aa9392d5a5" e何が起こっているのですか

module HasCompressedAttributes 
    def self.included(base) 
    base.extend ClassMethods 
    end 

    module ClassMethods 
    def has_compressed_attributes(*fields) 
     fields.each do |field| 
     define_method(:"#{field}=") do |uncompressed| 
      write_attribute(:"#{field}", Zlib::Deflate.deflate(uncompressed)) 
     end 

     define_method(:"#{field}") do 
      Zlib::Inflate.inflate(read_attribute(:"#{field}")) rescue nil 
     end 
     end 
    end 
    end 
end 

ActiveRecord::Base.class_eval{ include HasCompressedAttributes } 

もっと良いアプローチがありますか?多分既存の宝石ですか? PostgreSQLの最近のバージョンで

答えて

1

byteaのデフォルトの符号化方法は"hex"ある:

「ヘクス」フォーマットはバイトごとに2桁の16進数は、最上位ニブル最初ようにバイナリデータを符号化します。文字列全体の前にシーケンス\ x(エスケープ形式と区別するため)があります。

したがって、データベースに表示されている34bee1c2d099ba21da3ac...は、16進数でエンコードされたバイナリデータです。 textまたはvarchar(すなわち、t.textまたはt.string)ではなく、bytea列(つまり、列の作成時にt.binary)を使用している場合、ARがエンコードしてデコードする必要があります。バイナリデータをデータベースに格納する場合は、t.binaryを使用する必要がありますので、モジュール内でこの魔法を完全に隠すことはできません。スキーマも正しく設定する必要があります。

+0

私は 'bytea'カラムを使用していますが、エンコーディングはまだ間違っています(私はProdとDevで全く同じデータベースを使用していますが、Devでは動作しますが、Prodではうまく機能しません) –

+0

@Horace:Doあなたはdevとproductionで異なるPostgreSQLのバージョンを持っていますか? –

+0

良い呼び出し - 9.0.3のDev、9.0.6。それが違いを生み出すかどうかわかりません。 –

関連する問題