代码之家  ›  专栏  ›  技术社区  ›  mwilliams

在Rails模型中使用持续时间字段

  •  27
  • mwilliams  · 技术社区  · 15 年前

    我正在寻找在Rails模型中使用持续时间字段的最佳方法。我希望格式为hh:mm:ss(例如:01:30:23)。正在使用的数据库是本地的sqlite和生产中的postgres。

    我还想使用这个字段,这样我可以查看字段中的所有对象,并得出该模型中所有对象的总时间,最后得到如下结果:

    30条记录,共45小时、25分钟和34秒。

    那么什么才是最好的呢?

    • 迁移的字段类型
    • 积垢窗体的窗体字段(小时、分钟、秒下拉列表?)
    • 生成模型中所有记录的总持续时间的最便宜方法
    4 回复  |  直到 15 年前
        1
  •  41
  •   molf    15 年前
    • 以整数形式存储在数据库中(可能是秒数)。
    • 您的输入表单将取决于具体的用例。下拉是痛苦的;最好在小时+分钟+秒的时间内使用小文本字段。
    • 简单运行 SUM 查询Duration列以生成总计。如果您使用整数,这是容易和快速的。

    另外:

    • 使用助手在视图中显示持续时间。您可以轻松地将持续时间转换为秒整数 ActiveSupport::Duration 通过使用 123.seconds (替换) 123 使用数据库中的整数)。使用 inspect 关于结果 Duration 为了更好的格式。(这并不完美。你可能想自己写点东西。)
    • 在您的模型中,您可能需要返回/获取的属性读写器 活动支持::持续时间 对象,而不是整数。简单定义 duration=(new_duration) duration ,内部调用 read_attribute / write_attribute 带整数参数。
        2
  •  8
  •   ToTenMilan    7 年前

    在Rails 5中,可以使用ActiveRecord::attributes将ActiveSupport::Durations存储为ISO8601字符串。与整数相比,使用ActiveSupport::Duration的优势在于,您可以直接将其用于日期/时间计算。你可以做像 Time.now + 1.month 它总是正确的。

    以下是如何:

    添加 config/initializers/duration_type.rb

    class DurationType < ActiveRecord::Type::String
      def cast(value)
        return value if value.blank? || value.is_a?(ActiveSupport::Duration)
    
        ActiveSupport::Duration.parse(value)
      end
    
      def serialize(duration)
        duration ? duration.iso8601 : nil
      end
    end
    
    ActiveRecord::Type.register(:duration, DurationType)
    

    迁移

    create_table :somethings do |t|
      t.string :duration
    end
    

    模型

    class Something < ApplicationRecord
      attribute :duration, :duration
    end
    

    用法

    something = Something.new
    something.duration = 1.year    # 1 year
    something.duration = nil
    something.duration = "P2M3D"   # 2 months, 3 days (ISO8601 string)
    Time.now + something.duration  # calculation is always correct
    
        3
  •  5
  •   Turadg    14 年前

    我尝试使用activesupport::duration,但无法清除输出。

    你可能喜欢 ruby-duration ,不可变类型,表示以秒为单位的精确时间量。它有很多测试和MongoID模型字段类型。

    我还想轻松解析人工持续时间字符串,所以我选择了 Chronic Duration . 下面是一个例子,将它添加到一个在秒字段中花费时间的模型中。

    class Completion < ActiveRecord::Base
      belongs_to :task
      belongs_to :user
    
      def time_spent_text
        ChronicDuration.output time_spent
      end
    
      def time_spent_text= text
        self.time_spent = ChronicDuration.parse text
        logger.debug "time_spent: '#{self.time_spent_text}' for text '#{text}'"
      end
    
    end
    
        4
  •  3
  •   Envek    9 年前

    我写了一些存根来支持和使用PostgreSQL interval 类型为 ActiveRecord::Duration .

    请参见此要点(您可以将其用作Rails 4.1中的初始值设定项): https://gist.github.com/Envek/7077bfc36b17233f60ad

    此外,我还打开了对Rails的Pull请求: https://github.com/rails/rails/pull/16919