【问题标题】:Is there a way to back a new Rails 5 attribute with two database columns有没有办法用两个数据库列支持一个新的 Rails 5 属性
【发布时间】:2016-05-31 17:12:10
【问题描述】:

我正在考虑将新的Rails 5 attributes API 用于自定义数据类型,理想情况下将数据存储在两个数据库列中,一个用于数据value,另一个用于一些额外的type 信息。

属性 API 似乎设计为仅使用一个数据库列,我想知道我是否缺少使用两列的方法。

示例

想象一个 Money 对象,其中一个 decimalinteger 列用于价值,一个 string 列用于货币代码。我会传入我的自定义货币对象,将其存储两列,然后将其读回会将两列合并为一个 Money 对象。

我考虑过将值和货币序列化到单个 Postgres JSON 列中,但我希望能够执行快速 SQL SUM 查询并仅对值列进行排序,所以这似乎并不理想。

提前感谢您的任何见解。

【问题讨论】:

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


    【解决方案1】:

    我猜你正在考虑在你的模型中创建一个ValueObject

    为此有ActiveRecord::Aggregations。示例:

    class Customer < ActiveRecord::Base
      composed_of :balance, class_name: "Money", mapping: %w(balance amount)
    end
    
    class Money
      include Comparable
      attr_reader :amount, :currency
      EXCHANGE_RATES = { "USD_TO_DKK" => 6 }
    
      def initialize(amount, currency = "USD")
        @amount, @currency = amount, currency
      end
    
      def exchange_to(other_currency)
        exchanged_amount = (amount * EXCHANGE_RATES["#{currency}_TO_#{other_currency}"]).floor
        Money.new(exchanged_amount, other_currency)
      end
    
      def ==(other_money)
        amount == other_money.amount && currency == other_money.currency
      end
    
      def <=>(other_money)
        if currency == other_money.currency
          amount <=> other_money.amount
        else
          amount <=> other_money.exchange_to(currency).amount
        end
      end
    end
    

    【讨论】:

    • 哇,是的。聚合看起来很棒。我会四处寻找这些并在这里报告。谢谢你:)
    • 谢谢。它不完全适合我的用例(我需要对写入进行大量类型强制,使用模型中已有的数据)所以我最终继续使用我自己的 getter 和 setter。但这绝对是一个很好的答案,我下次学到了一个新技巧。
    【解决方案2】:

    很遗憾,无法直接回答您的问题,但您的示例让我思考。 money-rails gem 允许使用单独的货币列。也许值得挖掘那颗宝石,看看他们在幕后做了什么。

    【讨论】:

    • 是的,我们也是这么想的。我实际上已经为我当前的代码复制了他们现有的实现,它基本上只是覆盖了 getter 和 setter。现在有了 Rails 5 的官方属性 API,我想我会试一试。我搜索了money-rails gem GH 问题,但找不到任何关于新属性 API 的讨论。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-06
    • 2022-11-16
    • 2023-04-09
    • 1970-01-01
    相关资源
    最近更新 更多