有没有办法用两个数据库列来支持新的 Rails 5 属性
Is there a way to back a new Rails 5 attribute with two database columns
我正在考虑将新的 Rails 5 attributes API 用于自定义数据类型,理想情况下将数据存储在两个数据库列中,一个用于数据 value
,一个用于一些额外的 [=12] =] 信息。
属性 API 似乎设计为仅使用一个数据库列,我想知道我是否缺少使用两个列的方法。
例子
想象一个 Money 对象,其中一个 decimal
或 integer
列用于值,一个 string
列用于货币代码。我会传入我的自定义货币对象,将其存储两列,然后读回它会将两列组合成一个货币对象。
我考虑过将价值和货币序列化到单个 Postgres JSON 列中,但我希望能够仅对 SQL SUM
进行快速查询和排序值列,所以这看起来并不理想。
提前感谢您的任何见解。
很遗憾,无法直接回答您的问题,但您的示例让我开始思考。 money-rails gem 允许使用单独的货币列。也许值得深入研究 gem 看看他们在幕后做了什么。
我猜您正在考虑在您的模型中创建一个 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
我正在考虑将新的 Rails 5 attributes API 用于自定义数据类型,理想情况下将数据存储在两个数据库列中,一个用于数据 value
,一个用于一些额外的 [=12] =] 信息。
属性 API 似乎设计为仅使用一个数据库列,我想知道我是否缺少使用两个列的方法。
例子
想象一个 Money 对象,其中一个 decimal
或 integer
列用于值,一个 string
列用于货币代码。我会传入我的自定义货币对象,将其存储两列,然后读回它会将两列组合成一个货币对象。
我考虑过将价值和货币序列化到单个 Postgres JSON 列中,但我希望能够仅对 SQL SUM
进行快速查询和排序值列,所以这看起来并不理想。
提前感谢您的任何见解。
很遗憾,无法直接回答您的问题,但您的示例让我开始思考。 money-rails gem 允许使用单独的货币列。也许值得深入研究 gem 看看他们在幕后做了什么。
我猜您正在考虑在您的模型中创建一个 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