Use PostgreSQL's interval type as ActiveRecord::Duration

0

I couldn't bring myself to use an integer as a db column with the amazing interval available. Unfortunately Rails just sees it as a string, but here's how you can get it to work

class CreateAvailabilities < ActiveRecord::Migration[6.0]
  def change
    create_table :availabilities do |t|
      t.datetime   :starts_at, null: false
      t.interval   :duration,  null: false
    end
  end
end
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)
app/models/availability.rb
class Availability < ApplicationRecord
  attribute :duration, :duration

  def ends_at
    starts_at + duration
  end
end

You can then do stuff like this

irb(main):027:0> t1 = Time.now
irb(main):028:0> t2 = t1 + 10.minutes
irb(main):029:0> a = Availability.new(starts_at: t1, duration: (t2-t1).seconds)
irb(main):030:0> pp a
#<Availability:0x00007fb8be5199a0
 id: nil,
 starts_at: Sat, 08 Aug 2020 22:11:32 UTC +00:00,
 duration: 600.0 seconds>
irb(main):038:0> a.starts_at
=> Sat, 08 Aug 2020 22:11:32 UTC +00:00
irb(main):040:0> a.ends_at
=> Sat, 08 Aug 2020 22:21:32 UTC +00:00

https://stackoverflow.com/questions/1051465/using-a-duration-field-in-a-rails-model

  • 0 posts
  • 0 subtopics
  • about 2 months ago by vince