crashtech/torque-postgresql

Type casting support is missing

Closed this issue · 1 comments

mlt commented

It would be nice to have native ranges with support for infinity with a minimum efforts.

>> rng = ActiveRecord::Base.connection.select_one("select tstzrange('2019-01-01', 'Infinity', '[)')")['tstzrange']
=> "[\"2019-01-01 00:00:00+00\",infinity)"
>> rng.class
=> String
>> rng = ActiveRecord::Base.connection.select_all("select tstzrange('2019-01-01', 'Infinity', '[)')")
=> #<ActiveRecord::Result:0x0000000012ffde00 @columns=["tstzrange"], @rows=[["[\"2019-01-01 00:00:00+00\",infinity)"]], @hash_rows=nil, @column_types={"tstzrange"=>#<ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Range:0x0000000013936850 @subtype=#<ActiveRecord::ConnectionAdapters::PostgreSQL::OID::DateTime:0x00000000139368a0 @precision=nil, @scale=nil, @limit=nil>, @type=:tstzrange>}>
>> rng.column_types['tstzrange'].cast rng.first['tstzrange']
=> 2019-01-01 00:00:00 UTC...#<Date::Infinity:0x0000000010e19f00 @d=1>

Something along these lines could be worked into a concern or something

module ActiveRecordResultCast

  extend ActiveSupport::Concern

  def cast
    if Rails::VERSION::MAJOR >= 5
      self.map{|o| o.each{|k, v| o[k] = column_types[k].cast v}}
    else
      ...
    end
  end
end

ActiveRecord::Result.send(:include, ActiveRecordResultCast)

Then

>> rng.cast
=> [{"tstzrange"=>2019-01-01 00:00:00 UTC...#<Date::Infinity:0x000000000b314600 @d=1>}]
>> rng.cast.first['tstzrange']
=> 2019-01-01 00:00:00 UTC...#<Date::Infinity:0x000000000b314600 @d=1>

I don't know whether there is a way to make it work with like select_one without explicit #cast call. Would be nice though…

Edit

I also have

module DatetimeInfinity
  extend ActiveSupport::Concern

  def infinity(options = {})
    options[:negative] ? -::DateTime::Infinity.new : ::DateTime::Infinity.new
  end
end

ActiveRecord::ConnectionAdapters::PostgreSQL::OID::DateTime.send(:include, DatetimeInfinity)

Otherwise you end up with

>> rng.cast.first['tstzrange'].last.class
=> Float

I do have something that I'll be implementing similar to this. I needed it in a project, so I have a good solution. I'll be launching the 1.0.0 version with this okay?