Skip to content

Instantly share code, notes, and snippets.

@aquajach
Last active December 27, 2015 13:09
Show Gist options
  • Save aquajach/7331330 to your computer and use it in GitHub Desktop.
Save aquajach/7331330 to your computer and use it in GitHub Desktop.
[Monkey-Patch] Allow your rails4 to have a column as array of hash
module ActiveRecord
module ConnectionAdapters
class PostgreSQLAdapter < AbstractAdapter
module Quoting
def type_cast(value, column, array_member = false)
return super(value, column) unless column
case value
when Range
return super(value, column) unless /range$/ =~ column.sql_type
PostgreSQLColumn.range_to_string(value)
when NilClass
if column.array && array_member
'NULL'
elsif column.array
value
else
super(value, column)
end
when Array
case column.sql_type
when 'point' then PostgreSQLColumn.point_to_string(value)
when 'json' then PostgreSQLColumn.json_to_string(value)
else
return super(value, column) unless column.array
PostgreSQLColumn.array_to_string(value, column, self)
end
when String
return super(value, column) unless 'bytea' == column.sql_type
{ :value => value, :format => 1 }
when Hash
case column.sql_type
#aquajach: Add array_member
when 'hstore' then PostgreSQLColumn.hstore_to_string(value, array_member)
when 'json' then PostgreSQLColumn.json_to_string(value)
else super(value, column)
end
when IPAddr
return super(value, column) unless ['inet','cidr'].include? column.sql_type
PostgreSQLColumn.cidr_to_string(value)
else
super(value, column)
end
end
end
end
class PostgreSQLColumn < Column
module Cast
#aquajach: Add array_member as an option parameter
def hstore_to_string(object, array_member = false)
if Hash === object
object.map { |k,v|
"#{escape_hstore(k)}=>#{escape_hstore(v)}"
#aquajach: escape hstore when array_member exists
}.join(',').tap { |s| s.replace escape_hstore(s) if array_member }
else
object
end
end
def string_to_hstore(string)
if string.nil?
nil
elsif String === string
#aquajach: replace Hash with HashWithIndifferentAccess
HashWithIndifferentAccess[string.scan(HstorePair).map { |k,v|
v = v.upcase == 'NULL' ? nil : v.gsub(/\A"(.*)"\Z/m,'\1').gsub(/\\(.)/, '\1')
k = k.gsub(/\A"(.*)"\Z/m,'\1').gsub(/\\(.)/, '\1')
[k,v]
}]
else
string
end
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment