如何获得模型的原始预反序列化值?

时间:2017-07-30 02:51:05

标签: ruby-on-rails ruby-on-rails-5

我的模型中有加密类型

attribute :name, :encrypted

哪个是

class EncryptedType < ActiveRecord::Type::Text

并实施#serialize#deserialize#changed_in_place?

如何在反序列化之前从数据库中获取原始值?

我想创建一个rake任务来加密字段加密之前存在的DB中的值。因此,在加密之前,name字段包含Bob。使用加密更改代码后,读取该值将产生错误(捕获),返回空字符串。我想读取原始值并将其设置为普通属性,以便对其进行加密。加密后,该字段将显示为UD8yDrrXYEJXWrZGUGCCQpIAUCjoXCyKOsplsccnkNc=

我想要user.name_rawuser.raw_attributes[:name]之类的内容。

2 个答案:

答案 0 :(得分:3)

ActiveRecord::AttributeMethods::BeforeTypeCast

  

提供了一种在类型转换和反序列化之前读取属性值的方法

并且有read_attribute_before_type_castattributes_before_type_cast。此外,

  

它使用* _before_type_cast后缀

为所有属性声明了一个方法

例如:

User.last.created_at_before_type_cast # => "2017-07-29 23:31:10.862924"
User.last.created_at_before_type_cast.class # => String
User.last.created_at # => Sat, 29 Jul 2017 23:31:10 UTC +00:00
User.last.created_at.class # => ActiveSupport::TimeWithZone
User.last.attributes_before_type_cast # => all attributes before type casting and such

我认为这适用于您的自定义加密类型

答案 1 :(得分:0)

正如SimpleLime建议的那样......

namespace :encrypt do
  desc "Encrypt the unencrypted values in database"
  task encrypt_old_values: :environment do
    User.all.each do |user|
      if user.name.blank? && ! user.name_before_type_cast.blank?
        User.class_variable_get(:@@encrypted_fields).each do |att|
          user.assign_attributes att => user.attributes_before_type_cast[att.to_s]
        end
        user.save validate: false
      end
    end