diff options
Diffstat (limited to 'activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb')
-rw-r--r-- | activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb | 42 |
1 files changed, 26 insertions, 16 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb index 9270fc9f21..49dd4fc73f 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb @@ -12,8 +12,8 @@ module ActiveRecord def deserialize(value) if value.is_a?(::String) ::Hash[value.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') + 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 @@ -23,7 +23,9 @@ module ActiveRecord def serialize(value) if value.is_a?(::Hash) - value.map { |k, v| "#{escape_hstore(k)}=>#{escape_hstore(v)}" }.join(', ') + value.map { |k, v| "#{escape_hstore(k)}=>#{escape_hstore(v)}" }.join(", ") + elsif value.respond_to?(:to_unsafe_h) + serialize(value.to_unsafe_h) else value end @@ -33,25 +35,33 @@ module ActiveRecord ActiveRecord::Store::StringKeyedHashAccessor end + # Will compare the Hash equivalents of +raw_old_value+ and +new_value+. + # By comparing hashes, this avoids an edge case where the order of + # the keys change between the two hashes, and they would not be marked + # as equal. + def changed_in_place?(raw_old_value, new_value) + deserialize(raw_old_value) != new_value + end + private - HstorePair = begin - quoted_string = /"[^"\\]*(?:\\.[^"\\]*)*"/ - unquoted_string = /(?:\\.|[^\s,])[^\s=,\\]*(?:\\.[^\s=,\\]*|=[^,>])*/ - /(#{quoted_string}|#{unquoted_string})\s*=>\s*(#{quoted_string}|#{unquoted_string})/ - end + HstorePair = begin + quoted_string = /"[^"\\]*(?:\\.[^"\\]*)*"/ + unquoted_string = /(?:\\.|[^\s,])[^\s=,\\]*(?:\\.[^\s=,\\]*|=[^,>])*/ + /(#{quoted_string}|#{unquoted_string})\s*=>\s*(#{quoted_string}|#{unquoted_string})/ + end - def escape_hstore(value) - if value.nil? - 'NULL' - else - if value == "" - '""' + def escape_hstore(value) + if value.nil? + "NULL" else - '"%s"' % value.to_s.gsub(/(["\\])/, '\\\\\1') + if value == "" + '""' + else + '"%s"' % value.to_s.gsub(/(["\\])/, '\\\\\1') + end end end - end end end end |