Overriding to_h on dry-struct 1.3.0


We just upgraded to 1.3.0 and the upgrade broke us because of a to_h defined on one of our structs.

Given a Rails model with an attribute json_attribute (Postgres jsonb):

  • on 1.2.0 calling model.update(json_attribute: struct) works just fine and sets the JSON as the hash of struct’s attributes
  • on 1.3.0 however it seems that dry-struct internally calls to_h before saving and so the result saved in the DB is not struct’s attributes, but rather whatever overridden to_h returns.

It would be good to document that we shouldn’t be overriding to_h somewhere to avoid bugs like this. When going through changes I noticed https://github.com/dry-rb/dry-struct/pull/143 that seems to touch on this, but was later removed in https://github.com/dry-rb/dry-struct/pull/149. It seems like the deprecation has been rolled back, but the internal behaviour of the structs remained.

Please let me know if you need any additional info on this, thanks!

to_h in terms of structs has a special meaning, it’s not really surprising you run into issues. We could mention it in docs but it’s likely can be automated with a warning when to_h is redefined in a subclass. I’ll give it a shot. When it comes to changes in the repo itself, it was all intentional.

1 Like