在存储在Rails中的数据库之前透明地压缩属性

时间:2012-02-11 18:39:48

标签: ruby-on-rails database postgresql compression

我的一个模型有一个巨大的文本列,我想在将其存储到数据库之前进行压缩(不是为了节省磁盘空间,而是因为我不想通过网络发送未压缩字段我的数据库服务器到我的应用服务器)

我的数据库是postgresql,如果那是相关的

这是我尝试编写的扩展,但由于某种原因,这不适用于生产(实际存储在数据库中的数据看起来像十六进制(例如“34bee1c2d099ba21da3ac533d5f99cda2654feb73985430df39c5ffd8fbf9d9ff3aa9392d5a5”而不是Zlib输出(例如“A \ xEB \ xD3”) \ xF2Oy = \ x9C \ x7F5 \ xE9 \ xC44 \ x01M \“)。不确定发生了什么

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 }

这里有更好的方法吗?也许是现有的宝石?

1 个答案:

答案 0 :(得分:1)

最近版本的PostgreSQL中bytea的默认编码方法是"hex"

  

“十六进制”格式将二进制数据编码为每个字节2个十六进制数字,最重要的是半字节数字。整个字符串前面是序列\ x(以区别于转义格式)。

因此,您在数据库中看到的34bee1c2d099ba21da3ac...内容只是十六进制编码的二进制数据。如果您使用bytea列(即创建列时为t.binary而不是textvarchar(即{}},则AR应为您编码和解码该内容t.textt.string)。如果您要将二进制数据存储在数据库中,那么您必须使用t.binary,这样您就无法在模块中完全隐藏这种魔法,也必须正确设置模式。