'Is it possible to reliably execute a callback on an ActiveRecord jsonb column assignment or change?
I'm trying to execute some additional functionality in an ActiveRecord model when a jsonb column value is assigned to or when it changes.
My model is simple, it just contains a single jsonb column called payload. My current thinking is to override the column setter, but this doesn't seem to work as expected:
class Entity < ActiveRecord::Base
def payload=(jsonb)
pp 'Setter called...'
super(jsonb)
end
end
With the above model the following works:
ent = Entity.new
ent.payload = {}
#>> Setter called...
ent.save!
but subsequently the following syntax does not:
ent.payload["attribute"] = "value"
#>> ...
Is there any way to trigger code or fire a callback that works for both methods of assignment (inline and explict)?
I am aware that it is possible to hook into the ActiveModel dirty attributes to check if the jsonb value has changed at other points such as before_save, but these are reliant on active model callbacks.
I am specifically looking for a way to react to the change when it occurs, on assignment, not on subsequent events in the model life-cycle.
Solution 1:[1]
When you assign attribute / value, you call other method under the hood -- Hash#[]=
So if you decide to change its behavior you need to override like this
class Hash
def []=(key, val)
pp 'Setter called...'
super(key, val)
end
end
But keep in mind that such monkeypatch will affect not only this model, but everywhere when you will assign hash key
According to the comment you can define your own class
class TalkingHash < Hash
def []=(key, val)
pp 'Setter called...'
super(key, val)
end
end
ent = Entity.new
ent.payload = TalkingHash.new
# Setter called...
ent.payload[:nested] = TalkingHash.new
# Setter called...
ent.payload[:nested][:attribute] = :value
# Setter called...
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
