Skip to content

Commit 9c85851

Browse files
authored
Merge pull request rails#49934 from fatkodima/fix-pg-uuid-changed-formats
Fix PostgreSQL `Uuid#change?` to ignore uuid's value formatting
2 parents c0e67e6 + 2c98042 commit 9c85851

File tree

2 files changed

+18
-5
lines changed
  • activerecord
    • lib/active_record/connection_adapters/postgresql/oid
    • test/cases/adapters/postgresql

2 files changed

+18
-5
lines changed

activerecord/lib/active_record/connection_adapters/postgresql/oid/uuid.rb

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ module PostgreSQL
66
module OID # :nodoc:
77
class Uuid < Type::Value # :nodoc:
88
ACCEPTABLE_UUID = %r{\A(\{)?([a-fA-F0-9]{4}-?){8}(?(1)\}|)\z}
9+
CANONICAL_UUID = %r{\A[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}\z}
910

1011
alias :serialize :deserialize
1112

@@ -15,18 +16,27 @@ def type
1516

1617
def changed?(old_value, new_value, _new_value_before_type_cast)
1718
old_value.class != new_value.class ||
18-
new_value && old_value.casecmp(new_value) != 0
19+
new_value != old_value
1920
end
2021

2122
def changed_in_place?(raw_old_value, new_value)
2223
raw_old_value.class != new_value.class ||
23-
new_value && raw_old_value.casecmp(new_value) != 0
24+
new_value != raw_old_value
2425
end
2526

2627
private
2728
def cast_value(value)
28-
casted = value.to_s
29-
casted if casted.match?(ACCEPTABLE_UUID)
29+
value = value.to_s
30+
format_uuid(value) if value.match?(ACCEPTABLE_UUID)
31+
end
32+
33+
def format_uuid(uuid)
34+
if uuid.match?(CANONICAL_UUID)
35+
uuid
36+
else
37+
uuid = uuid.delete("{}-").downcase
38+
"#{uuid[..7]}-#{uuid[8..11]}-#{uuid[12..15]}-#{uuid[16..19]}-#{uuid[20..]}"
39+
end
3040
end
3141
end
3242
end

activerecord/test/cases/adapters/postgresql/uuid_test.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,13 @@ def test_invalid_uuid_dont_match_to_nil
121121
assert_empty UUIDType.where(guid: "foobar")
122122
end
123123

124-
def test_uuid_change_case_does_not_mark_dirty
124+
def test_uuid_change_format_does_not_mark_dirty
125125
model = UUIDType.create!(guid: "abcd-0123-4567-89ef-dead-beef-0101-1010")
126126
model.guid = model.guid.swapcase
127127
assert_not_predicate model, :changed?
128+
129+
model.guid = "{#{model.guid}}"
130+
assert_not_predicate model, :changed?
128131
end
129132

130133
class DuckUUID

0 commit comments

Comments
 (0)