In Sequel, I can do:
irb(main):003:0> DB[\"select false\"].get
=> false
Which returns a false boolean. I\'d like to be able to do so
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 names
res.map{|row|row.map{|col,val|res.column_types[col].type_cast val}}
# Don't care about no column names
res.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
I don't know if it is the way, but you can create activerecord model without table with sort of fake column:
class FunctionValue < ActiveRecord::Base
def self.columns
@columns ||= [];
end
def self.column(name, sql_type = nil, default = nil, null = true)
columns << ActiveRecord::ConnectionAdapters::Column.new(
name.to_s,
default,
sql_type.to_s,
null
)
end
column :value, :boolean
end
And then you can run this:
function_value = FunctionValue.find_by_sql('select false as value').first
function_value.value
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}}
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_map
res[0]
# => {"a"=>"abc", "b"=>123, "float8"=>1.23}
In Rails 6, Person.connection.select_all(sql_query).to_a
...will return an array of hashes whose values are type-casted. Example:
[{"id"=>12, "name"=>"John Doe", "vip_client"=>false, "foo"=> nil, "created_at"=>2018-01-24 23:55:58 UTC}]
If you prefer an OpenStruct
, use Mike's suggestion:
Person.connection.select_all(sql_query).to_a.map {|r| OpenStruct.new(r) }
If you prefer symbols as keys, call map(&:symbolize_keys)
after to_a
.
This works for me in rails 5
results = ActiveRecord::Base.connection.select_all(sql)
results.rows.map{ |row| Hash[results.columns.zip(row)] }
Gives nice results
[{"person1"=>563, "person2"=>564, "count"=>1},
{"person1"=>563, "person2"=>566, "count"=>5},
{"person1"=>565, "person2"=>566, "count"=>1}]