Using a duration field in a Rails model

前端 未结 4 1158
温柔的废话
温柔的废话 2021-01-30 07:00

I\'m looking for the best way to use a duration field in a Rails model. I would like the format to be HH:MM:SS (ex: 01:30:23). The database in use is sqlite locally and Postgr

4条回答
  •  野趣味
    野趣味 (楼主)
    2021-01-30 07:59

    In Rails 5, you can use ActiveRecord::Attributes to store ActiveSupport::Durations as ISO8601 strings. The advantage of using ActiveSupport::Duration over integers is that you can use them for date/time calculations right out of the box. You can do things like Time.now + 1.month and it's always correct.

    Here's how:

    Add 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)
    

    Migration

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

    Model

    class Something < ApplicationRecord
      attribute :duration, :duration
    end
    

    Usage

    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
    

提交回复
热议问题