Getting typed results from ActiveRecord raw SQL Getting typed results from ActiveRecord raw SQL postgresql postgresql

Getting typed results from ActiveRecord raw SQL


While I have no doubt that Björn Nilsson's answer worked when he posted it, it is failing for me with Postgres 9.4 and PG gem version 0.18.2. I have found the following to work after looking through the PG gem documentation:

pg = ActiveRecord::Base.connection@type_map ||= PG::BasicTypeMapForResults.new(pg.raw_connection)res = pg.execute("SELECT 'abc'::TEXT AS a, 123::INTEGER AS b, 1.23::FLOAT;")res.type_map = @type_mapres[0]# => {"a"=>"abc", "b"=>123, "float8"=>1.23}


Pretty ugly but does what you are asking for:

res = ActiveRecord::Base.connection.select_all("select 1 as aa, false as aas, 123::varchar, Array[1,2] as xx")# Breaks unless returned values have unique column namesres.map{|row|row.map{|col,val|res.column_types[col].type_cast val}}# Don't care about no column namesres.map{|row|  row.values.map.with_index{|val,idx|    res.column_types.values[idx].type_cast val  }}

gives:

[[1, false, "123", [1, 2]]]

How it works:

res.column_types

returns a hash of columns names and Postgresql column types

Here is a pointer to how it works:https://github.com/rails/docrails/blob/fb8ac4f7b8487e4bb5c241dc0ba74da30f21ce9f/activerecord/lib/active_record/connection_adapters/postgresql/oid/float.rb


Don't have enough reputation points to respond, but Bjorn's answer and associated replies are broken in Rails 5. This works:

res = ActiveRecord::Base.connection.select_all(sql)res.to_a.map{|o| o.each{|k, v| o[k] = res.column_types[k].cast v}}