'How trigger a callback after a nullify in rails
model 1:
class Programmer
has_many :tasks, dependent: :nullify
end
model 2:
class Task
belongs_to :programmer
end
Programmer has many tasks. When I destroy a programmer, his tasks should be nullified (programmer_id = nil), but also his tasks should be setup to open (status = 'open'), independent of it current status.
I'd like to when destroy programmer, besides nullify programmer_id, set status attribute in task to 'open', but nullify not trigger callbacks
I don't know how to make this because :nullify don't trigger callback, only :destroy
Solution 1:[1]
As you say, dependent: :nullify doesn't trigger callbacks. I would probably define a method a little higher up the stack (in a Service or some such) that knows how to delete a programmer and then set the status on all the previously associated tasks.
If you really want to do it automatically, though, another option is to use the ActiveSupport instrumentation API to hook all SQL execution and do a comparison there:
ActiveSupport::Notifications.subscribe "sql.active_record" do |*args|
data = args.extract_options!
if data[:sql] == "UPDATE \"tasks\" SET \"programmer_id\" = NULL WHERE \"tasks\".\"programmer_id\" = $1"
Task.where(programmer_id: nil, status: 'assigned').update_all(status: 'open')
end
end
Solution 2:[2]
I'd suggest a more visible approach so that others reading the code know what is happening:
class Programmer
has_many :tasks
before_destroy :nullify_tasks
private
def nullify_tasks
tasks.update programmer: null
end
end
This will trigger callbacks on each of the updated tasks. dependent: :nullify actually just adds a callback like this anyway but does something more like tasks.update_all programmer: null (thus skipping the callbacks).
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 | Tom Copeland |
| Solution 2 | Brendon Muir |
