Rails 5 和 PostgreSQL 'Interval'数据类型[英] Rails 5 and PostgreSQL 'Interval' data type

本文是小编为大家收集整理的关于Rails 5 和 PostgreSQL 'Interval'数据类型的处理方法,想解了Rails 5 和 PostgreSQL 'Interval'数据类型的问题怎么解决?Rails 5 和 PostgreSQL 'Interval'数据类型问题的解决办法?那么可以参考本文帮助大家快速定位并解决问题。

问题描述

Rails 真的不能正确支持 PostgreSQL 的间隔数据类型吗?

我不得不使用 this Stack Overflow answer 来自2013 创建一个区间列,现在看来我需要使用 这段代码 从 2013 年开始,让 ActiveRecord 将间隔视为字符串以外的内容.

是这样吗?我最好只使用整数数据类型来表示分钟数吗?

推荐答案

从 Rails 5.1 开始,您可以使用 postgres 'Interval' 数据类型,因此您可以在迁移中执行以下操作:

add_column :your_table, :new_column, :interval, default: "2 weeks"

虽然ActiveRecord只把interval当做字符串处理,但是如果你在你的postgresql数据库中将IntervalStyle设置为iso_8601,它会以iso8601的风格显示这个interval:2 weeks => P14D

execute "ALTER DATABASE your_database SET IntervalStyle = 'iso_8601'"

然后您可以直接将列解析为 ActiveSupport::Duration

在您的 model.rb

def new_column
  ActiveSupport::Duration.parse self[:new_column]
end

有关 ISO8601 间隔的更多信息,请访问 https://en.wikipedia.org/wiki/ISO_8601#Time_intervals

其他推荐答案

我遇到了类似的问题,并为 ActiveRecord 模型上的特定列定义了读取器方法.像这样:

class DivingResults < ActiveRecord::Base
  # This overrides the same method for db column, generated by rails
  def underwater_duration
    interval_from_db = super
    time_parts = interval_from_db.split(':')
    if time_parts.size > 1 # Handle formats like 17:04:41.478432
      units = %i(hours minutes seconds)
      in_seconds = time_parts
        .map.with_index { |t,i| t.to_i.public_send(units[i]) }
        .reduce(&:+) # Turn each part to seconds and then sum
      ActiveSupport::Duration.build in_seconds
    else # Handle formats in seconds
      ActiveSupport::Duration.build(interval_from_db.to_i)
    end
  end
end

这允许在别处使用 ActiveSupport::Duration 实例.希望 Rails 在不久的将来开始自动处理 PostgreSQL 间隔数据类型.

其他解决方案

Rails 6.1 提供了更完整和集成的解决方案


当前的答案建议覆盖模型中的读者和作者.我接受了 alter database 建议 和 为 ISO8601 间隔构建了一个 gem,ar_interval.

提供了一个简单的ActiveRecord::Type为您处理 ISO8601 字符串的序列化和转换!

测试包括以下示例如何使用它.

如果有兴趣,Sam Soffes 演示的其他格式可以是包含在测试中

本文地址:https://www.itbaoku.cn/post/1763852.html