palkan / logidze

Database changes log for Rails
MIT License
1.59k stars 74 forks source link

JSONB column and switch_to! with append: true #217

Closed miharekar closed 1 year ago

miharekar commented 1 year ago

I have a Cafe model with JSONB opening_times. They're stored like this:

irb(main):045:0> cafe.opening_times
=>
{"friday"=>{"open"=>"07:00", "close"=>"19:00"},
 "monday"=>{"open"=>"07:00", "close"=>"19:00"},
 "sunday"=>{"open"=>"07:00", "close"=>"19:00"},
 "tuesday"=>{"open"=>"07:00", "close"=>"19:00"},
 "saturday"=>{"open"=>"07:00", "close"=>"19:00"},
 "thursday"=>{"open"=>"07:00", "close"=>"19:00"},
 "wednesday"=>{"open"=>"07:00", "close"=>"19:00"}}

If I then switch_to a version, everything is fine. But if I chose append: true the JSONB gets mangled like so:

irb(main):053:0> cafe.switch_to!(6, append: true)
  TRANSACTION (0.2ms)  BEGIN
  Cafe Update (1.1ms)  UPDATE "cafes" SET "updated_at" = $1, "opening_times" = $2, "web" = $3 WHERE "cafes"."id" = $4  [["updated_at", "2022-12-22 13:27:05.684779"], ["opening_times", "\"{\\\"friday\\\": {\\\"open\\\": \\\"07:00\\\", \\\"close\\\": \\\"19:00\\\"}, \\\"monday\\\": {\\\"open\\\": \\\"07:00\\\", \\\"close\\\": \\\"19:00\\\"}, \\\"sunday\\\": {\\\"open\\\": \\\"07:00\\\", \\\"close\\\": \\\"19:00\\\"}, \\\"tuesday\\\": {\\\"open\\\": \\\"07:00\\\", \\\"close\\\": \\\"19:00\\\"}, \\\"saturday\\\": {\\\"open\\\": \\\"07:00\\\", \\\"close\\\": \\\"19:00\\\"}, \\\"thursday\\\": {\\\"open\\\": \\\"07:00\\\", \\\"close\\\": \\\"19:00\\\"}, \\\"wednesday\\\": {\\\"open\\\": \\\"07:00\\\", \\\"close\\\": \\\"19:00\\\"}}\""], ["web", "https://www.longstoryshort.cz/"], ["id", 1204]]
Enqueued LegacyCafeUpdateJob (Job ID: 6e7bca36-4d55-4467-8ab3-78afdddc9303) to Sidekiq(default) with arguments: #<GlobalID:0x000000010d281050 @uri=#<URI::GID gid://ect/Cafe/1204>>
Enqueued UrlCheckerJob (Job ID: 9eae1543-22b3-41f0-a52c-51b1a0a0c440) to Sidekiq(low) with arguments: #<GlobalID:0x000000010d2785b8 @uri=#<URI::GID gid://ect/Cafe/1204>>
  TRANSACTION (0.4ms)  COMMIT
=> true
irb(main):054:0> cafe.opening_times
=> "{\"friday\": {\"open\": \"07:00\", \"close\": \"19:00\"}, \"monday\": {\"open\": \"07:00\", \"close\": \"19:00\"}, \"sunday\": {\"open\": \"07:00\", \"close\": \"19:00\"}, \"tuesday\": {\"open\": \"07:00\", \"close\": \"19:00\"}, \"saturday\": {\"open\": \"07:00\", \"close\": \"19:00\"}, \"thursday\": {\"open\": \"07:00\", \"close\": \"19:00\"}, \"wednesday\": {\"open\": \"07:00\", \"close\": \"19:00\"}}"

Version 6 does not contain any changes to opening_times JSONB column:

{"c"=>{"web"=>"[URL redacted]", "updated_at"=>"2022-12-22 13:27:05.684779"}, "v"=>6, "ts"=>1671715625685},

As far as I understand from the codebase: switch_to with append: true calls History#changes_to which calls Version#changes which returns the data JSON dump which includes the unparsed JSONB string.

#<Logidze::History:0x000000010cd2a4d0
 @data=
  {"h"=>
    [{"c"=>
       {"id"=>1204,
        "wifi"=>true,
        "about"=>"",
        "lunch"=>true,
        "snacks"=>false,
        "status"=>1,
…
        "opening_times"=>
         "{\"friday\": {\"open\": \"07:00\", \"close\": \"19:00\"}, \"monday\": {\"open\": \"07:00\", \"close\": \"19:00\"}, \"sunday\": {\"open\": \"07:00\", \"close\": \"19:00\"}, \"tuesday\": {\"open\": \"07:00\", \"close\": \"19:00\"}, \"saturday\": {\"open\": \"07:00\", \"close\": \"19:00\"}, \"thursday\": {\"open\": \"07:00\", \"close\": \"19:00\"}, \"wednesday\": {\"open\": \"07:00\", \"close\": \"19:00\"}}",
…
        "water_filtration_system"=>""},
      "v"=>1,
      "ts"=>1670672468390},

I believe that opening_times should be returned as JSON cast/parsed in Version#changes which would then also fix this switch_to issue.

But I leave it up to you to confirm this and how/where exactly to do this.

The way I got around it is to do:

cafe.assign_attributes(cafe.at(version:).attributes)
cafe.save!
palkan commented 1 year ago

Yeah, we definitely missing type-casting somewhere.

UPD: yeah, we need to call #deserialize_changes before updating the record: https://github.com/palkan/logidze/blob/3c9ce510845203ac5cec5affb4fa439b66ad1f9d/lib/logidze/model.rb#L178

Would you like to submit a PR?)

miharekar commented 1 year ago

Great, thanks for pointing me in the right direction!

Yup, sure.