mysql - Rails 2 hook 在读取/写入 MySQL DB 之前修改数据

标签 mysql ruby-on-rails hook rails-activerecord ruby-on-rails-2

我有一个 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/

相关文章:

MySQL - 将表 1 中每个更新的行插入表 2

jquery - 获取 ajax 请求时 Rails 中的 500 内部服务器错误

c++ - C 宏的使用 '##' 和 '###' 也是指针

c - 如何防止二进制文件上的 LD_PRELOAD?

mysql - 如何在mysql中将句子拆分为单词

php - 如何确保脚本在执行前完全执行?

PHP strtotime() : date showing '1970-01-01 ' after conversion

ruby-on-rails - ruby-1.9.3-p125 ssl 错误

ruby-on-rails - 如何强制 Jruby 使用内置的 Ruby 1.9 而不是默认的 Ruby 1.8?

linux - Git - 自动 pull 入服务器