如何转换ActiveRecord属性to/from数据库?

How to transform ActiveRecord attributes to/from the database?

问题

是否有内置 API、第 3 方 Gem 或通用范例,用于在 Rails 应用程序中对数据进出数据库应用转换?

注意:我不是在寻找助手、视图模型或标准 before/after ActiveRecord 挂钩。我需要能够悄悄地改变数据 "underneath" 通常的挂钩,这样机制 decoupled/hidden/unknown 到应用程序的其余部分。

换句话说,我希望在 ActiveRecord 中正常挂钩下方的某处以及数据库适配器上方某处的每个属性的基础上插入一个垫片,这将允许我透明地处理数据,就像序列化程序一样对于数据库适配器。

简单的例子

$ rails new test-app
$ cd test-app
$ bundle install
$ bundle exec rails g scaffold vehicle make model year:integer color
$ bundle exec rake db:migrate

app/models/vehicle.rb 中,类似于:

class Vehicle < ActiveRecord::Base
  magic_shim :color, in: :color_upcase, out: :color_downcase

  private
    # Returns a modified value for storage but does not change the
    # attribute value in the ActiveRecord object.
    def color_upcase
      self.color.upcase
    end

    # Accepts the stored value and returns an inversely modified version
    # to be used by the ActiveRecord attribute.
    def color_downcase(stored)
      stored.downcase
    end
end

在rails控制台中(注意"Red"的大写):

irb> truck = Vehicle.create make: "Ford", model: "F150", year: 2015, color: "Red"

在rails数据库中(颜色在存储前被大写):

sqlite> SELECT * FROM `vehicles`;
1|Ford|F150|2015|RED|2015-06-24 16:07:33.176769|2015-06-24 16:07:33.176769

然后返回控制台(应用程序看到小写版本):

irb> truck = Vehicle.find 1
irb> truck.color
=> red

(从评论移至回答)

在这种情况下,覆盖默认访问器可以解决问题。 更多信息和实现代码示例:http://api.rubyonrails.org/classes/ActiveRecord/Base.html#class-ActiveRecord%3a%3aBase-label-Overwriting+default+accessors