Skip to content

Instantly share code, notes, and snippets.

@TomTriple
Created June 17, 2011 11:56
Show Gist options
  • Save TomTriple/1031281 to your computer and use it in GitHub Desktop.
Save TomTriple/1031281 to your computer and use it in GitHub Desktop.
ActiveRecord::PostgreSQLAdapter#result_as_array
# create a 2D array representing the result set
def result_as_array(res) #:nodoc:
#
# check if we have any binary column and if they need escaping
ftypes = Array.new(res.nfields) do |i|
[i, res.ftype(i), res.fname(i)]
end
rows = res.values
typehash = ftypes.group_by { |_, type| type }
# this addition will perform conversion from your aggregate function used in Model.select to int
# OID types used by Postgres: http://doxygen.postgresql.org/include_2catalog_2pg__type_8h.html
# ===> Integer 8-bit equals "20"
# START
integer8 = typehash[20] || []
rows.each do |row|
integer8.each do |index, _|
row[index] = row[index].to_i
end
end
# END
return rows unless ftypes.any? { |_, x|
x == BYTEA_COLUMN_TYPE_OID || x == MONEY_COLUMN_TYPE_OID
}
binaries = typehash[BYTEA_COLUMN_TYPE_OID] || []
monies = typehash[MONEY_COLUMN_TYPE_OID] || []
rows.each do |row|
# unescape string passed BYTEA field (OID == 17)
binaries.each do |index, _|
row[index] = unescape_bytea(row[index])
end
# If this is a money type column and there are any currency symbols,
# then strip them off. Indeed it would be prettier to do this in
# PostgreSQLColumn.string_to_decimal but would break form input
# fields that call value_before_type_cast.
monies.each do |index, _|
data = row[index]
# Because money output is formatted according to the locale, there are two
# cases to consider (note the decimal separators):
# (1) $12,345,678.12
# (2) $12.345.678,12
case data
when /^-?\D+[\d,]+\.\d{2}$/ # (1)
data.gsub!(/[^-\d.]/, '')
when /^-?\D+[\d.]+,\d{2}$/ # (2)
data.gsub!(/[^-\d,]/, '').sub!(/,/, '.')
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment