我有一个 Rails 2 应用程序,我正在尝试修改它,以便在将属性写入我的 MySql 数据库之前对其进行编码,并在读取时对其进行解码(不是所有属性,只是预先确定的属性)。
我看过一些 gems,特别是 attr 加密的,但它并没有完全按照我的要求进行(我也试图避免重命名我现有的任何表列,这似乎是 attr 的要求-加密)。
我在我的模型中添加了一个 before_save 过滤器,以便在将其保存到数据库之前进行属性修改,并且我已经覆盖了我的属性 getter 来进行解码。虽然这可行,但我想在堆栈的较低位置进行解码(即在读取数据库后立即进行解码)以使所有功能正常运行,而无需进行系统范围的更改(它还简化了决定何时编码/解码时的逻辑)。
所以这意味着我要执行以下操作:
1) 在读取数据库时,执行相反的操作,这样如果我执行 Model.last,我的属性值将是解码后的值(无需显式调用属性 getter)。
2) 覆盖 find_by_* 方法,这样通过我的编码属性进行搜索将首先对搜索词进行编码,然后使用该值进行数据库查询。
我该怎么做呢?
最佳答案
更新:不幸的是,此方法在 Rails 2 中不起作用。自定义序列化程序可能已添加到 Rails 3 中。
原始答案如下:
我认为您可以尝试使用 serializer 中描述的自定义 this blog post 。即使在 Rails 2 中也应该存在此功能(否则我猜这些关于它的 SO questions 将不存在)。
将属性编码为 Base64 的示例序列化器:
# app/models/model.rb
class Model < ActiveRecord::Base
serialize :my_attr, MyEncodingSerializer
end
# lib/my_encoding_serializer.rb
class MyEncodingSerializer
require "base64"
def self.load(value)
# called when loading the value from DB
value.present? ? Base64.decode64(value) : nil
end
def self.dump(value)
# called when storing the value into DB
value.present? ? Base64.encode64(value) : nil
end
end
在 Rails 控制台中测试:
>> Model.create(my_attr: "my secret text")
D, [2016-03-14T07:17:26.493598 #14757] DEBUG -- : (0.1ms) BEGIN
D, [2016-03-14T07:17:26.494676 #14757] DEBUG -- : SQL (0.6ms) INSERT INTO `models` (`my_attr`) VALUES ('bXkgc2VjcmV0IHRleHQ=\n')
D, [2016-03-14T07:17:26.499356 #14757] DEBUG -- : (4.4ms) COMMIT
=> #<Model id: 4, my_attr: "my secret text">
您可以看到 my_attr
值在保存到数据库之前会自动编码。
从数据库加载当然也是透明的:
>> Model.last
D, [2016-03-14T07:19:01.414567 #14757] DEBUG -- : Model Load (0.2ms) SELECT `models`.* FROM `models` ORDER BY `models`.`id` DESC LIMIT 1
=> #<Model id: 4, my_attr: "my secret text">
所有的 finder helpers 也应该工作,例如:
>> Model.find_by_my_attr("other text")
D, [2016-03-14T07:20:06.125670 #14757] DEBUG -- : Model Load (0.3ms) SELECT `models`.* FROM `models` WHERE `models`.`my_attr` = 'b3RoZXIgdGV4dA==\n' LIMIT 1
=> nil # nothing found here for wrong my_attr value
>> Model.find_by_my_attr("my secret text")
D, [2016-03-14T07:21:04.601898 #14757] DEBUG -- : Model Load (0.6ms) SELECT `models`.* FROM `models` WHERE `models`.`my_attr` = 'bXkgc2VjcmV0IHRleHQ=\n' LIMIT 1
=> #<Model id: 4, my_attr: "my secret text"> # FOUND!
关于mysql - Rails 2 hook 在读取/写入 MySQL DB 之前修改数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35973633/