#mysql #ruby-on-rails #ruby #ruby-on-rails-3 #zlib
#mysql #ruby-on-rails #ruby #ruby-on-rails-3 #zlib
Вопрос:
Мне нужно сжать большой фрагмент текста перед сохранением его в базе данных и распаковать его обратно, как только клиент его запросит.
Метод, который я использую прямо сейчас, кажется, работает нормально, когда я вставляю новые записи с помощью консоли Rails и сразу запрашиваю только что вставленную запись. т. Е. Я могу успешно распаковать сжатое описание.
Но я не могу распаковать сжатый description
файл для любой из моих других записей, добавленных до этой даты. Это действительно сбивает меня с толку, особенно будучи новичком в мире ROR.
Я использую MySQL в качестве базы данных.
Смотрите мою модель ниже, чтобы лучше понять ее.
require "base64"
class Video < ActiveRecord::Base
before_save :compress_description
def desc
unless description.blank?
return decompress(description)
end
end
private
def compress_description
unless description.blank?
self.description = compress(description)
end
end
def compress(text)
Base64.encode64(Zlib::Deflate.new(nil, -Zlib::MAX_WBITS).deflate(text, Zlib::FINISH))
end
def decompress(text)
Zlib::Inflate.new(-Zlib::MAX_WBITS).inflate(Base64.decode64(text))
end
end
Комментарии:
1. Не могли бы вы рассказать мне, как именно вы используете эту модель. Я попробовал то же самое, и у меня это работает просто отлично. Я подозреваю, что, возможно, вы используете описание вместо метода desc при поиске незашифрованной строки, но я хотел бы подтвердить, так ли это.
2. @user420504: Нет, я использую
desc
и для меняdesc
работает, если я получаю вставленные записи в тот же день. Но если я попытаюсь извлечь ту же запись через пару дней, это просто даст мнеjunk
Ответ №1:
Хорошо, на самом деле очень легко воспроизвести вашу проблему. В консоли rails выполните следующие действия
Video.create(:description => "This is a test")
Video.last.description
=> "C8nILFYAokSFktTiEgA=n"
Video.last.desc
=> "This is a test"
Video.last.save #This update corrupts the description
Video.last.desc
=> "C8nILFYAokSFktTiEgA=n"
Причина повреждения заключается в том, что вы сжимаете уже сжатую строку
Вероятно, вам следует изменить свой класс следующим образом, и все должно быть в порядке
require 'base64'
class Video < ActiveRecord::Base
before_save :compress_description
after_find :decompress_description
attr_accessor :uncompressed_description
private
def compress_description
unless @uncompressed_description.blank?
self.description = compress(@uncompressed_description)
end
end
def decompress_description
unless description.blank?
@uncompressed_description = decompress(description)
end
end
def compress(text)
Base64.encode64(Zlib::Deflate.new(nil, -Zlib::MAX_WBITS).deflate(text, Zlib::FINISH))
end
def decompress(text)
Zlib::Inflate.new(-Zlib::MAX_WBITS).inflate(Base64.decode64(text))
end
end
Теперь используйте свой класс следующим образом
Video.create(:uncompressed_description => "This is a test")
Video.last.description
=> "C8nILFYAokSFktTiEgA=n"
Video.last.uncompressed_description
=> "This is a test"
Video.last.save
Video.last.uncompressed_description
=> "This is a test"