【问题标题】:How to transform ActiveRecord attributes to/from the database?如何在数据库中转换 ActiveRecord 属性?
【发布时间】:2015-06-24 16:26:32
【问题描述】:

问题

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

注意:我不是在寻找助手、视图模型或标准的 before/after ActiveRecord 挂钩。我需要能够在通常的钩子“下方”默默地改变数据,以便该机制对应用程序的其余部分来说是解耦/隐藏/未知的。

换句话说,我希望在 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

【问题讨论】:

  • 覆盖默认访问器有什么问题? (api.rubyonrails.org/classes/ActiveRecord/…)
  • 只是转换可能相对复杂,因此必须在每次访问属性时执行,而不仅仅是查询。我想我可以追求默认访问器覆盖并使用某种缓存,但我会担心意外的边缘情况(想想脏检查等)。
  • ...但既然您已经让我深入思考了这一点,我想它只需要在属性更改时进行转换,这不是什么大问题。
  • @dimuch 发表答案,我会接受;你帮我解释了为什么访问器覆盖 正确的解决方案。

标签: ruby-on-rails database activerecord hook transform


【解决方案1】:

(从 cmets 转移到答案)

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-01
    • 1970-01-01
    相关资源
    最近更新 更多